简体   繁体   中英

Aurelia - Change the color of the selected row in a table

I am using Aurelia v4.6.1 with Typescript in a.Net core project. I have a component that retrieves data from an external source and displays it in a table using a repeat.for attribute.

Now I want to highlight the row that has been selected (clicked). On my view model I have a documents property of type Document[] that holds all the documents displayed in the grid, and I have a selectedDocument property of type Document that should hold the last selected document. This is set in a click event on the row setSelected.

My view is as follows:

<template>
<require from="../../resources/valueconverters/itemIdFormat"></require>
<require from="./documentData.css"></require>
<h1>Patient Documents</h1>

<p>This component demonstrates fetching data from DME.</p>

<p if.bind="!documents"><em>Loading...</em></p>

<table if.bind="documents" class="table">
    <thead>
        <tr>
            <th>Id</th>
            <th>Title</th>
            <th>Patient</th>
        </tr>
    </thead>
    <tbody>
        <tr repeat.for="document of documents" click.trigger="setSelected(document)" class="${($document.title == $selectedDocument.title) ? 'selected' : 'notSelected'}">
            <td>${ document.itemId | itemIdFormat }</td>
            <td>${ document.title }</td>
            <td>${ document.patient.lastName}, ${ document.patient.firstName }</td>
        </tr>
    </tbody>
</table>

My ViewModel class is:

import { HttpClient } from 'aurelia-fetch-client';
import { BindingEngine, inject } from 'aurelia-framework';

@inject(HttpClient, BindingEngine)
export class DocumentData {
public documents: Document[];
public selectedDocument: Document;
public bindingEngine

constructor(http: HttpClient, bindingEngine) {
    this.bindingEngine = bindingEngine;
    this.selectedDocument = null;
    let subscription = this.bindingEngine
        .propertyObserver(this, 'selectedDocument')
        .subscribe(this.selectedDocumentChanged);


    http.fetch('/api/Data/PatientDocuments')
        .then(result => result.json() as Promise<Document[]>)
        .then(data => {
            this.documents = data;
        });
}

setSelected(selected: Document) {
    this.selectedDocument = selected;
}

selectedDocumentChanged(newValue, oldValue) {
   // this.documents.forEach(function (d) {
   //     d.isCurrent = d === newValue;
   // })
}
}

As you can see in the view html, I have set the class attribute on the table row element with:

class="${($document.title == $selectedDocument.title) ? 'selected' : 'notSelected'}"

However for some reason this always returns true so all rows are highlighted.

So I tried this instead:

class="${$document.isCurrent ? 'selected' : 'notSelected'}"

Then I used the binding engine subscribe function on the selectedDocument property, setting it to run selectedDocumentChanged method, to set the isCurrent property on each document in the list manually whenever the selectedDocument property is changed. Notice however that this is commented out. This is because the this variable is not in scope in the subscriber changed method so I can't use it.

So I am a bit stuck. What is the correct way to highlight the selected row? I guess it might be possible using a nested component repeated for each row, but I would prefer to be able to achieve this all in this component.

Firstly - the scope issue you're getting with the selectedDocumentChanged() method is because you're using the Binding Engine. If you use the observable decorator instead like below, this will no longer be out of scope;

import {observable} from "aurelia-framework";

export class DocumentData {

    @observable selectedDocument;

    // Your other code

    selectedDocumentChanged(newVal, oldVal) {
        this.documents.forEach(function (d) { // no longer out of scope
            d.isCurrent = d === newValue;
        })
    }
}

Secondly - in your template you don't need to prefix your properties with a $ . This is only used when you want to use string interpolation within your templates. If you're looping through, or comparing properties then you can just use them as normal. For example;

class="${document.isCurrent ? 'selected' : 'notSelected'}"

or;

class="${(document.title == selectedDocument.title) ? 'selected' : 'notSelected'}"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM