-1

I have the following html:

<li>
 <select class="variation">
  <option value="1">1</option>
  <option value="2">2</option>
 </select>
 <p class="price"></p>
</li>

This is duplicated multiple times (list of products).

By default the first options price is displayed next to the dropdown, works fine, when i change the select it should change the price to the price of the selected option, that works fine BUT it doesn't hide just the other price for that product, it hides it for every product.

My JS:

$(".build-box-list li").each(function() {
 $(".variation", this).on("change", function() {
  $(".price").hide();
  $("#" + this.value).show();
 });
});

How do I hide just the price in the specific product li and not every product, I did try $(".price", this).hide(); without success.

Thanks

Gareth Gillman
  • 343
  • 1
  • 4
  • 20
  • Possible duplicate of [$(this) selector and children?](http://stackoverflow.com/questions/306583/this-selector-and-children) – PeeHaa Dec 01 '16 at 10:23

1 Answers1

1

From the code/html provided, the issue is this line:

$(".price").hide();

which does not have any context, so applies to all .price elements.

it hides it for every product

The event is on .variation, so to get the related .price you can use a number of methods, my preference is to go up to the parent and then back down (you could also use .siblings and .nextAll (or event .next if you're daring) if your html is unlikely to change in the future (which it probably will...)).

$(".build-box-list li").each(function() {
 $(".variation", this).on("change", function() {
  $(this).closest("li").find(".price").hide();
  $("#" + this.value).show();
 });
});

As an extra, you can remove the loop:

$(".build-box-list li .varation").on("change", function() {
  $(this).closest("li").find(".price").hide();
  $("#" + this.value).show();
});

See this answer for more options / reasons.

Community
  • 1
  • 1
freedomn-m
  • 27,664
  • 8
  • 35
  • 57
  • 1
    why not just use `$(this).next('.price')` instead of going up to the parent and back down – Pete Dec 01 '16 at 10:32
  • @Pete as I mentioned, this is an option. However, it leads to very brittle code and many people don't understand exactly how `.next` works (see the numerous questions on SO on this subject...). Eg if you change the html to `

    ` then `$("select").next(".price")` would stop working. It might work *now* in this *exact* scenario, but any changes would break it. See [here](http://stackoverflow.com/a/40426392/2181514) for some more options.

    – freedomn-m Dec 01 '16 at 10:55
  • "very brittle code" I'm guessing the structure is as likely to change as the code being within an `li` (it would actually be more likely to move it out of the li as it seems a bit odd in there). Doing closest would also be "brittle" as you put it. In this case if you are bothered about brittleness, you could just use `parent()` by itself which would be a faster selector – Pete Dec 01 '16 at 11:08
  • @Pete I agree. A higher container would normally have a class which would be referenced in the `.closest()`, rather than using a `li`. Any selector will cause brittleness and there are arguments for/against any. Generally (IMO), it's best to code to allow the most likely changes to the html (ie not using .next or .parent) - on the other hand, if you're micro-optimising the code and html changes are a lower priority than runtime efficiency, then `$(this).next()` would be fine, in this case. – freedomn-m Dec 01 '16 at 11:35