Aurelia SlickGrid - How to set an initial state of customElement

I have Aurelia SlickGrid installed and its working.

I am using a detailed view that you click an icon on the left side to reveal the panel.

the panel is using that same icon to mimic the action of the SlickGrid panel display only this time it actually displays a list of visits using the map function.

This actually all works however I would like the first row of jobs to be initialized in the reverse. I would like the first job to be open so to speak and the visits to show. The code is far better at explaining this than me.

First here is how it renders at the moment:

I would like that first icon but not the rest of the icons if there were more lines, just the first to be inverted. That is I want it to be displaying the visits for the top job.

eg

Here is the CustomElement that displays the panel:

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

@autoinject
export class ClientIndexDetailViewCustomElement {
    @bindable detailViewRowCount = 7;
    @bindable visits;
    @bindable iconState: number;

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

    @bindable() model: {
        id: number;
        clientNo: string;
        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;
        } else if (overrideContext && overrideContext.bindingContext && overrideContext.bindingContext.model) {
            this.model = overrideContext.bindingContext.model;
        } else if (overrideContext && overrideContext.parentOverrideContext && overrideContext.parentOverrideContext.bindingContext && overrideContext.parentOverrideContext.bindingContext.model) {
            this.model = overrideContext.parentOverrideContext.bindingContext.model; {
            }
        }
    }

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

    rowSelected() { }
}

Here is the view:

<template>
	<require from="./ObjectKeysValueConverter"></require>
	<div class="container-fluid">
		<div class="row reduceFont">
			<div class="col-3 border-right">
				<h6>Client Details - ${model.clientNo}</h6>
				<address>
					<div if.bind="model.company">
						<strong>Company Name:</strong>
						<div>
							<span>${model.companyName}</span>
						</div><br />
						<div if.bind="model.isWarrantyCompany">
							<strong><input type="checkbox" checked.bind="model.isWarrantyCompany" disabled> Warranty Company</strong>
						</div>
					</div><br />
					<div if.bind="model.company">
						<span><strong>Contact Name:</strong></span>
					</div>
					<div else>
						<strong>Full Name:</strong>
					</div>
					<b>${model.clientLastName}</b>, ${model.clientFirstName}<br />
					<br />
					<strong>Address:</strong><br>
					${model.address.address1}<br>
					<!--<span if.bind=${model.address.address2}>${model.address.address2}</span>-->
					${model.address.suburb.suburbName} ${model.address.suburb.postCode}<br>
					${model.address.suburb.state.stateShortName}<br>
					<br />
					<strong>Phone:</strong><br>
					${model.mobilePhone}<br>
				</address>

			</div>
			<div class="col-9">
				<h6>Job Details</h6>
				<div class="table-wrapper-scroll-y jobs-scrollbar">
					<table class="table table-sm table-hover table-striped">
						<thead>
							<tr>
								<th></th>
								<th class="sg-column">Job No</th>
								<th class="sg-column">Agent</th>
								<th class="sg-column">Agents Job No.</th>
								<th class="sg-column">Job Type:</th>
								<th class="sg-column">Status:</th>
								<th class="sg-column">No. of Visits</th>
							</tr>
						</thead>
						<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 class="sg-column">${job.warrantyCompany}</td>
								<td class="sg-column">${job.agentJobNo}</td>
								<td class="sg-column">${job.Type}</td>
								<td class="sg-column">${job.status}</td>
								<td class="sg-column">${job.numberOfVisits}</td>
							</tr>
						</tbody>
					</table>
				</div>

				<div>
					<div><i class="fa fa-list font-awesome-closed" aria-hidden="true"></i>  <strong><i>Visits...</i></strong></div>
					<div class="row">
						<div class="table-wrapper-scroll-y visits-scrollbar">
							<table class="table table-sm table-hover table-striped">
								<thead>
									<tr>
										<th class="sg-column">Visit Date:</th>
										<th class="sg-column">Start Time:</th>
										<th class="sg-column">End Time:</th>
									</tr>
								</thead>
								<tbody>
									<tr repeat.for="visit of visits">
										<td class="sg-column"><strong>${visit.visitDate}</strong></td>
										<td class="sg-column">${visit.startTime}</td>
										<td class="sg-column">${visit.endTime}</td>
									</tr>
								</tbody>
							</table>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

In the view, its this line that determines if the visits display or not.

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

and of course its this method…

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

that will duly show the visits once the icon is clicked… the “dash” icon shows as well as the visits.

Given there is a list of jobs showing with “plus” icons showing at the start of each line… how could I make the top row default to the “dash” icon and show the visits?

Nice to see such complex implementation in a Row Detail. I haven’t used it yet even though I built it in the lib lol.

If I understand your question, it’s not about Aurelia-Slickgrid itself but more about how to open the sub-section inside the Row Detail, is that correct? I’m not sure if that would work, but wouldn’t that be possible to call the iconSelected after you’ve set the bindings?

bind(bindingContext, overrideContext) {
   // the binding code
   this.iconSelected(this.model.jobs[0].id)`
}

I might have misunderstood the question though.

1 Like

Nailed it. Yes the row detail makes me look a lot better than I really am… :smile: Thanks for implementing it.

1 Like

Glad that works, I would suggest to add a flag in your ViewModel to know if it’s open or close so that you can still toggle it on the next time you click on it so that you keep it in sync.

Side note, I’m not sure why you have the aureliaGrid, gridOptions and columnDefinitions in your Row Detail ClientIndexDetailViewCustomElement, these properties are not technically called neither available directly in the Row Detail, though you can access them all with latest version when I added a way to reference the parent ViewModel as shown in the Row Detail - Wiki

Would you mind sharing the CSS/SASS styling you’ve done for this Row Detail? I could add a link to this discourse in the Row Detail Wiki and your print screen shown on top, just to show others what could be done with this feature. :wink:

2 Likes