Home > Blockchain >  Changing current text for custom HTML dropdowns
Changing current text for custom HTML dropdowns

Time:07-22

I'm creating a set of dropdowns with a custom look so I've built these using divs and checkboxes rather than the usual element

I'm looking to change the 'select-wrapper--title' text (e.g. the first option) to whatever is selected in the dropdown

I'm having some trouble doing this with multiple dropdowns, it seems to change the title for all of them instead of just the dropdown I'm interacting with. I think I need a loop but I'm not sure how to go about this logic

I've created a JSFiddle of my code here: https://jsfiddle.net/m9h32nzq/6/

But here is the code here too:

$(function() {
  $(".filter-grid .select-wrapper--title").on("click", function() {
    var index = $(this).index(".select-wrapper--title");

    console.log(index);

    if ($(".select-wrapper.open").length >= 1) {
      if ($(this).parents(".select-wrapper").hasClass("open")) {
        $(".filter-grid .select-wrapper.open").removeClass("open");
      } else {
        //Close other filter boxes if open
        $(".filter-grid .select-wrapper.open").removeClass("open");
        $(".filter-grid .select-wrapper").eq(index).addClass("open");
      }
    } else {
      $(".filter-grid .select-wrapper").eq(index).addClass("open");
    }
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <div >
    <div >
      <label >No. of Nights</label>
      <div >
        <label >
          <input type="checkbox"  value="">
          1 Night
        </label>
        <label >
          <input type="checkbox"  value="">
          2 Nights
        </label>
        <label >
          <input type="checkbox"  value="">
          3 Nights
        </label>
      </div>
    </div>
  </div>
  <div >
    <div >
      <label >No. of People</label>
      <div >
        <label >
          <input type="checkbox"  value="">
          1 Person
        </label>
        <label >
          <input type="checkbox"  value="">
          2 People
        </label>
        <label >
          <input type="checkbox"  value="">
          3 People
        </label>
      </div>
    </div>
  </div>
</div>

CodePudding user response:

Assuming I've understood what you're asking, you want the text label for the dropdown to be filled with the text labels of the selected checkboxes within each instance.

To do this you simply need to use DOM traversal to find the checked boxes within the current dropdown. From there you can build an array of their values using map(). You can also provide a default value for the dropdown in a data attribute for the cases where no checkboxes are selected.

Also note that you can massively simplify the code you're using to show/hide the dropdown options. All you need is toggleClass().

Taking this a step further, you can hook an event handler to the document to hide the dropdown when the user clicks outside of it.

With all that said, here's a working example updated to ES6.

jQuery($ => {
  // show dropdown on click inside
  $(".filter-grid .select-wrapper--title").on("click", e => {
    e.stopPropagation();
    $(e.currentTarget).closest('.select-wrapper').toggleClass('open');
  });

  // hide dropdowns on click outside
  $(document).on('click', e => {    
        if ($(e.target).closest('.select-filter').length == 0)
        $('.select-wrapper').removeClass('open');
  });
  
  // set dropdown text on checkbox update
  $('.filter-grid :checkbox').on('change', e => {   
    let $container = $(e.target).closest('.select-wrapper');
    let values = $container.find(':checkbox:checked').map((i, el) => el.value).get().join(', ');
    if (!values) 
        values = $container.find('.select-wrapper--title').data('default');
      
    $container.find('.select-wrapper--title').text(values);
  });
});
.filter-grid {
  margin-bottom: 10px;
  max-width: 300px
}

.filter-grid .select-filter {
  padding: 5px 10px 5px 0;
  z-index: 99
}

.filter-grid .select-filter .select-wrapper {
  flex: 0 0 100%;
  display: block;
  position: relative;
  width: 100%
}

.filter-grid .select-filter .select-wrapper:after {
  border: 5px solid transparent;
  border-right-color: orange;
  border-bottom-color: orange;
  position: absolute;
  top: 16px;
  right: 15px;
  content: "";
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  z-index: 1
}

.filter-grid .select-filter .select-wrapper .select-wrapper--title {
  position: relative;
  display: block;
  font-weight: 500;
  cursor: pointer;
  border: 2px solid orange;
  padding: 12px 35px 12px 20px;
  color: orange;
  font-family: museo-slab, serif
}

.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown {
  overflow-y: hidden;
  max-height: 0;
  position: relative;
  z-index: 9;
  background: white;
  box-shadow: 0 4px 5px 0 rgba(0, 0, 0, 0.4);
  opacity: 1;
  visibility: hidden;
  min-width: 150px;
  overflow: hidden
}

.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown div {
  padding: 10px
}

.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown .select-item {
  display: block;
  width: 100%;
  line-height: normal;
  padding: 5px 0 5px 17px
}

.filter-grid .select-filter .select-wrapper .select-wrapper--dropdown .select-item .checkbox {
  top: 7px
}

.filter-grid .select-filter .select-wrapper.open .select-wrapper--dropdown {
  max-height: 250px;
  overflow-y: auto;
  opacity: 1;
  visibility: visible
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div >
  <div >
    <div >
      <label  data-default="No. of Nights">No. of Nights</label>
      <div >
        <label >
          <input type="checkbox"  value="1 Night">
          1 Night
        </label>
        <label >
          <input type="checkbox"  value="2 Nights">
          2 Nights
        </label>
        <label >
          <input type="checkbox"  value="3 Nights">
          3 Nights
        </label>
      </div>
    </div>
  </div>
  <div >
    <div >
      <label  data-default="No. of People">No. of People</label>
      <div >
        <label >
          <input type="checkbox"  value="1 Person">
          1 Person
        </label>
        <label >
          <input type="checkbox"  value="2 People">
          2 People
        </label>
        <label >
          <input type="checkbox"  value="3 People">
          3 People
        </label>
      </div>
    </div>
  </div>

</div>

One last thing to note is that the values in your controls don't make sense. A user shouldn't be allowed to select multiple selections from wither dropdown. For example, how can I possibly book '1 Night' and '3 Nights' at the same time? I assume this is because this is just a learning exercise, and not for a production system.

CodePudding user response:

I made the following changes to your code:

  • type="radio" instead of type="checkbox" so you dont need additional logic to uncheck other boxes

  • Wrap the dropdown item text in a span so you can read it easily

  • Added JS code at the bottom which does what you eventually want.

      <div >
          <div >
              <label >No. of Nights</label>
    
              <div >
                  <label >
                      <input type="radio"  name="item" value="">
                      <span>1 Night</span>
                  </label>
                  <label >
                      <input type="radio"  name="item" value="">
                      <span>2 Nights</span>
                  </label>
                  <label >
                      <input type="radio"  name="item"value="">
                      <span>3 Nights</span>
                  </label>
              </div>
    
          </div>
      </div>
    
      <div >
          <div >
              <label >No. of People</label>
    
              <div >
                  <label >
                      <input type="radio"  name="item" value="">
                      <span>1 Person</span>
                  </label>
                  <label >
                      <input type="radio"   name="item" value="">
                      <span>2 People</span>
                  </label>
                  <label >
                      <input type="radio"   name="item" value="">
                      <span>3 People</span>
                  </label>
              </div>
    
          </div>
      </div>
    
$('[name="item"]').each(function() {
    $(this).on('click', function(e) {
    const target = $(e.target);
    const name = target.next().html();
    console.log(target.parent().parent().prev());
    target.parent().parent().prev().html(name);
  });
});
  • Related