5

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.

4 Answers 4

4

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>
3

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>
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.

0

You can use a property on your class to store the index then increment on your get method. Ex:

Using "active" property on if:

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

on your class create a index property and implement getter for active:

index = 0;

get active(){
    //increment index inside brackets cause we can't after return
    return this.reviews[this.index++].Id === activeReviewId
}

this way, every time foreach runs, it increments index and get the correct data to compare

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .