How would I translate that from Aura to LWC?
<aura:iteration items="{!v.contacts}" var="contact">
<div class="{!contact.isActive ? 'slds-tabs--path dimmed' : 'slds-tabs--path'}">...</div>
</aura:iteration>
The documentation covers this explicitly:
To compute a value for a property, use a JavaScript getter. For example, to convert the name to all uppercase letters, use a getter function in the JavaScript class, not an expression in the template.
Getters are much more powerful than expressions because they’re JavaScript functions. Getters also enable unit testing, which reduces bugs and increases fun.
Your example code would look like this:
<!-- MyComponent.html -->
<div class={tabClass}>
// MyComponent.js
get tabClass() {
return this.active ? 'slds-tabs--path dimmed' : 'slds-tabs--path';
}
Your concerns about separating UI from controller logic do not apply here as this is not a "controller". That MVC pattern is an Aura-ism. This is the code which drives your component's functionality so it makes sense that your JS would know about class names.
Edit:
After you changed your question, I think the best way to do what you're trying to do is to have a custom "contact" component which when clicked, becomes active, and has an
@api active;
property, which you can call from the parent. In your comments below you say this is too much overhead, but this is the proper way to do this if you wish to manage the state of the contact. In your code example you are only toggling one class, but in a real world scenario there are many different things which you might want to change about a contact and having many expressions makes the code harder to read and harder to test.
For most list items the suggestion is to have an individual element for each list item like so:
<c-list>
<c-list-item></c-list-item>
<c-list-item></c-list-item>
<c-list-item></c-list-item>
</c-list>
className
property on each item. <template for:each={items} for:item="item"><div class={item.className}></div></template>
I was at a LWC presentation last night, and I think this recipe might get you on the right track: https://github.com/trailheadapps/easy-spaces-lwc/blob/develop/es-space-mgmt/main/default/lwc/customerTile/customerTile.js
The parent List component creates child tiles - notice how the getter references the object and customer object that are passed in to set the alttext. That recipe also shows how selecting something in the parent component can change the css in the child if I understood it correctly.
Parent:
<li class="slds-item" key={record.Id}>
<c-customer-tile
customer={record} object={sobject} oncustomerselect={publishSelect}>
</c-customer-tile>
</li>
Child HTML:
<lightning-icon icon-name={icon} alternative-text={alttext}></lightning-icon>
JS
import { LightningElement, api, track } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
export default class CustomerTile extends NavigationMixin(LightningElement) {
@api customer;
@api object;
@track navRef;
get icon() {
return 'standard:' + this.object.toLowerCase();
}
get alttext() {
return (
'Navigate to ' +
this.object +
' record detail for ' +
this.customer.name
);
}
get
.