3

I'm trying to output a list of strings separated by commas in LWC, such as:

cat, dog, mouse

I need to use template for:each and output a list item and a comma, but only if the item is not the last in the list. But I'm having trouble since LWC does not support comparison operations in templates. I tried to set a field in JS to indicate which element is the last:

HTML:

<template for:each={animals.data} for:item="animal">
    <b key={animal.Id}>{animal.Name}</b>
    <template if:false={animal.isLast}>
        ,&nbsp;
    </template>
</template>

JS:

@wire(getAnimals)
assignAnimals(animals) {
    this.animals = animals;
    if (this.animals.data && this.animals.data.length > 0) {
        this.animals.data[this.animals.data.length - 1].isLast = true;
    }
}

But I cannot assign to this.animals.data[this.animals.data.length - 1].isLast because JS Proxy is guarding it.

TypeError: "proxy set handler returned false for property '"isLast"'"

The other options would be to create isLast field in the controller, but I would need to create a wrapper class. Another possibility would be some CSS tricks, but I don't want to do that.

Is there any simple way to do this?

1
  • the "proxy" you get is immutable, you can however, create a new array based on the proxy and then do a Join by ',' to output your desired string.
    – glls
    Commented Jun 11, 2019 at 16:12

2 Answers 2

9

Just as addition to gNerbs answer:

if you really need or want a own component you can use the iterator directive which has a first / last item attribute

Like:

<template>
    <template iterator:it={animals}>
        <c-child key={it.value.key} animal={it.value.value} is-last={it.last}></c-child>
    </template>
</template>

Full Example for your Reference: https://developer.salesforce.com/docs/component-library/tools/playground/qaI8LcEzj/1/edit

Link to Docs: https://developer.salesforce.com/docs/component-library/documentation/lwc/create_lists

4

Build your string in Javascript and just display it to the page as opposed to using the for:each template.

@track animalString;

@wire(getAnimals)
assignAnimals(animals) {
    this.animals = animals;

    this.animalString = this.animals.join(', ');
}

Then:

<span>{!animalString}</span>

Or what ever element/component you want to use to display your string.

4
  • 3
    this.animalString = this.animals.join(', ');
    – sfdcfox
    Commented Jun 11, 2019 at 16:11
  • Nice! But it only works if I actually need to output a string - which I indeed do in this case. But what if I wanted to, for example, create a child component in an iteration and pass "isLast" as a parameter to this component? I wonder if there is some more general solution. But your solution works for my case this time, thanks again :)
    – mmm321321
    Commented Jun 11, 2019 at 16:14
  • @Renji-xD I think your answer is probably exactly what OP is looking for. You should past it as a separate answer as I'm sure it will be accepted.
    – gNerb
    Commented Jun 11, 2019 at 18:07
  • ok i added it - just don`t wanted to hijack your answer which is still valid of course ;)
    – Renji-xD
    Commented Jun 11, 2019 at 18:21

You must log in to answer this question.

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