3

I'm stuck on how to conditionally render (let alone apply styles) while in a for:each according to an expression.

<lightning-layout-item padding="around-small"> <div class="header-column"> <p class="field-title" title="Active">Active</p> <template for:each={reviews} for:item="review"> <template if:true={review.Id === activeReviewId}> // this doesn't work <p> key={review.Id}>X</p> </template> </template> </div> </lightning-layout-item>

All I'm trying to do, is if the review.Id matches the currently active Id, add an "X" next to the item. I can't use a get expression handler because while the handler knows about this.activeReviewId, it doesn't receive any params so it can't evaluate if the current index being iterated upon matches. I know how to do this with a parent/child relationship, but I just literally want to put an "X" next to the active review, and creating three files seems insane.

Any suggestions welcome, thank you.

3 Answers 3

2

Your example doesn't work because LWC doesn't allow computations inside template expressions. This is by design because we believe that this type of logic belongs in your javascript. Doing the following will simplify your template and facilitate the testing of your component:

get activeReview() {
  return this.reviews.find(review => review.Id === this.activeReviewId);
}
<lightning-layout-item padding="around-small">
  <div class="header-column">
    <p class="field-title" title="Active">Active</p>
    <!-- Render markup using {activeReview.*} here -->
  </div>
</lightning-layout-item>
1

Eugene and Kasper are both correct about the limitations around template expressions, but I'm going to try to provide an answer that's hopefully a little closer to what you're looking for to solve your problem.

You didn't go into detail about how activeReviewId gets set, but if I were in your shoes, I would adjust that so that it sets a Boolean property on each object in the reviews array instead of something like activeReviewId. For example, you may have an onclick event like this:

onReviewClick(event) {
    this.activeReviewId = event.target.id;
}

Replace that with:

onReviewClick(event) {
    this.reviews.forEach(review => {
        review.isActive = (review.Id === event.target.id);
    }
}

Then, in your template, you can do this:

<template for:each={reviews} for:item="review">
    <template if:true={review.isActive}> 
        <p key={review.Id}>X</p>
    </template>
</template>
0

You can't use formulas in your template if true expression. The easiest solution would be to use javascript to create a new list that only contains the items you want to display. This has the advantage that you have the full power of JavaScript at your disposal, and that your html file only handles displaying data, while your JavaScript file handles the logic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.