1

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?

  • 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 Jun 11 '19 at 16:12
6

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

3

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.

  • 3
    this.animalString = this.animals.join(', '); – sfdcfox Jun 11 '19 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 Jun 11 '19 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 Jun 11 '19 at 18:07
  • ok i added it - just don`t wanted to hijack your answer which is still valid of course ;) – Renji-xD Jun 11 '19 at 18:21

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.