Changing classes on the fly that are part of a repeat.for table

I have created a table that displays a small number of rows as part of a custom element.

I want to be able to click on a fontawesome icon “fa fa-plus-circle” at the start of each row which will fire a delegate while, at the same time, change that icon to a “fa fa-minus-circle”… If I click on it again
it changes back to a plus icon and so on - toggling… where “icon-??” is either true or “false”.

The problem here is that its part of a repeat.for loop so I’ve used ${$index} to locate the index and build that into the repeat…

<tr repeat.for="job of model.jobs">
	<td click.delegate='iconSelected(job.id, $index)'><i class="${icon-$index ? 'fa fa-plus-circle' : 'fa fa-minus-circle' }"></i></td>

This way I could ensure a unique class variable to bind to.

I figured that if that variable was “true” then it would show the first part of the ternary and if its false it would show the second part and you could toggle just by manipulating the boolean value of that var.

However I am having trouble setting all the vars to true as a @bindable and also initiating the individual variables values = “true” as part of an initiating the object.

There could be one row or there could be 5 or 7 so I wanted to be able to create the bindings at the time based on the number of rows from the model.jobs binding.

import { bindable, autoinject } from "aurelia-framework";
import {
	AureliaGridInstance,
	Column,
	GridOption
} from 'aurelia-slickgrid';

@autoinject
export class ClientIndexDetailViewCustomElement {
	@bindable detailViewRowCount = 7;
	@bindable visits;
	@bindable clicked = false;

	@bindable jobRowIcons = {};

	aureliaGrid: AureliaGridInstance;
	gridOptions: GridOption;
	columnDefinitions: Column[];


	@bindable() model: {
		id: number;
		clientNo: number;
		company: boolean;
		isWarrantyCompany: boolean;
		CompanyName: string;
		ClientFirstName: string
		ClientLastName: string
		MobilePhone: string
		DateCreated: string
		DeActivated: string
		NumberOfJobs: string
		Active: boolean
		Activity: boolean
		Address: any
		jobs: any[]
	};

	bind(bindingContext, overrideContext) {

		if (bindingContext.model) {
			this.model = bindingContext.model;
			console.log("client-detail-MODEL 1: ", this.model);
		} else if (overrideContext && overrideContext.bindingContext && overrideContext.bindingContext.model) {
			this.model = overrideContext.bindingContext.model;
			console.log("client-detail-MODEL 2: ", this.model);
		} else if (overrideContext && overrideContext.parentOverrideContext && overrideContext.parentOverrideContext.bindingContext && overrideContext.parentOverrideContext.bindingContext.model) {
			this.model = overrideContext.parentOverrideContext.bindingContext.model; {
				console.log("client-detail-MODEL 3: ", this.model);
			}
		}

		for (var i = 0; i < this.model.jobs.length; i++) { // SET THE VALUE OF ICON-i HERE....
			this.jobRowIcons['icon-' + i] = true;
		}
	}

	iconSelected(jobId: number, index: number) {  // If a job is selected then the visits for the job are displayed next to the job list on the form.
		console.log("jobId and Index: ", jobId, index);
	}
}

Ive tried to set the value of icon-0, icon-1… all to “true” here

		for (var i = 0; i < this.model.jobs.length; i++) { // SET THE VALUE OF ICON-i HERE....
			this.jobRowIcons['icon-' + i] = true;
		}

However I dont know how to bind that to ternary operator in the template… how can I set the value of each var in this.jobRowIcons and make it set the ternary in the template?

I found this unusually hard…

I found a workaround. What I wanted was to click on an icon and it would show a table of visits for that job. The jobs were displayed in a table using repeat.for so how could you individually change an icon if you clicked on the icon.

I used a ternary to check if a @bindable variable called iconState was equal to the index of the table row. If it was the class would be, instead, another fontawesome icon.

					<tbody>
						<tr repeat.for="job of model.jobs">
							<td click.delegate='iconSelected(job.id, $index)'><i class="${iconState == $index ? 'fa fa-minus-circle font-awesome-open' : 'fa fa-plus-circle font-awesome-closed' }"></i></td>
							<td class="sg-column"><strong>${job.jobNo}</strong></td>
							<td>${job.warrantyCompany}</td>
							<td class="sg-column-right">${job.agentJobNo}</td>
							<td>${job.jobType}</td>
							<td>${job.status}</td>
							<td class="sg-column">${job.numberOfVisits}</td>
						</tr>

If you clicked on the icon a click.delegate would run the method “iconSelected” which among other things would set the variable iconState (which is @bindable) to the row index. Clicking on it again would change it back by clearing iconState and the visits array. It works but I suspect better programmers than me would find a more elegant solution.

iconSelected(jobId: number, index: number) {  // If a job is selected then the visits for the job are displayed next to the job list on the form.
    console.log("jobId and Index: ", jobId, index);
    if (this.iconState == index) {
        this.iconState = null;
        this.visits = null;
    } else {
    let job = this.model.jobs.filter(f => f.id === jobId);
    if (job && job.length > 0) {
        this.iconState = index;
        var jobVisits = job.map(j => { return j.jobVisits; })[0];
        this.visits = jobVisits;
        console.log("VISITS: ", this.visits);
        }
    }
}