Pertanyaan Aurelia: Computed / Observable in repeat.for


Saya memiliki beberapa data yang dapat diedit dalam sebuah tabel dengan jumlah untuk baris dan kolom yang akan dihitung.

Example of table

Karena saya ingin memiliki kode html yang lebih sederhana, saya menggunakan repeat.for untuk membangun baris-baris tabel. Untuk membangun jumlah, saya menggunakan fungsi, yang merupakan cara terbaik yang saya miliki sampai sekarang.

Sayangnya, jumlah tidak diperbarui dengan cara ini ketika saya mengedit nilainya. Fungsi pengambil akan dihitung, tetapi mereka tidak dapat mengambil parameter.

Saya tahu saya bisa menulis sesuatu seperti $ {$ parent.data [y] ['Q1'] + $ parent.data [y] ['Q2'] + ...} tetapi ini menjadi agak panjang dan apa 'Q1' di contoh ini akan menjadi sesuatu yang dinamis dalam kehidupan nyata. Dan untuk jumlah kolom saya akan memiliki 15 baris yang harus dijumlahkan - saya lebih suka tidak harus menulis pernyataan penjumlahan dalam html untuk itu.

Saya sedang melihat observatorlocator tetapi tidak mengerti bagaimana saya bisa menggunakannya untuk kasus saya. Saya pikir ini adalah szenario yang agak sederhana jadi saya harap ada solusi bagus untuk sesuatu seperti ini di Aurelia.

test.js

export class Test {
    data = {
        "2015": { "Q1": 7318, "Q2": 6215, "Q3": null, "Q4": 3515 },
        "2016": { "Q1": 1234, "Q2": 2345, "Q3": 3345, "Q4": 3000 },
        "2017": { "Q1": 4233, "Q2": 999, "Q3": 1234, "Q4": 3268 },
        "2018": { "Q1": 7375, "Q2": 4415, "Q3": 8415, "Q4": 1005 },
        "2019": { "Q1": null, "Q2": 5698, "Q3": 1254, "Q4": 6635 }
    };

    years() {
        return Object.keys(this.data);
    }

    sumY(y) {
        var sum = 0;
        Object.values(this.data[y])
            .forEach(function(item){
                sum += item;
            });
        return sum;
    }

    sumQ(q) {
        var sum = 0;
        Object.values(this.data)
            .forEach(function(item) {
                sum += item[q];
            });
        return sum;
    }
}

test.html

    <template>
    <table>
        <thead>
            <tr>
                <td>Year</td>
                <td>Q1</td>
                <td>Q2</td>
                <td>Q3</td>
                <td>Q4</td>
                <td>Sum</td>
            </tr>
        </thead>
        <tbody>
            <tr repeat.for="y of years()">
                <td>${y}</td>
                <td><input type="text" value.bind="$parent.data[y]['Q1']" /></td>
                <td><input type="text" value.bind="$parent.data[y]['Q2']" /></td>
                <td><input type="text" value.bind="$parent.data[y]['Q3']" /></td>
                <td><input type="text" value.bind="$parent.data[y]['Q4']" /></td>
                <td class="ansatz">${$parent.sumY(y)}</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <td>Sum</td>
                <td>${sumQ("Q1")}</td>
                <td>${sumQ("Q2")}</td>
                <td>${sumQ("Q3")}</td>
                <td>${sumQ("Q4")}</td>
            </tr>
        </tfoot>
    </table>
</template>

4
2017-10-06 09:07


asal


Jawaban:


Ketika fitur pengikatan-perilaku dilepaskan, kita akan dapat menggunakan perilaku pengikatan "sinyal" untuk menamai pengikatan nilai dan penjumlahan penjumlahan. Kemudian kita akan dapat "memberi sinyal" penjumlahan jumlah untuk me-refresh ketika perubahan-perubahan nilai berubah.

Dalam versi Aurelia saat ini Anda dapat menambahkan argumen "sinyal" ke sumY dan sumQ ekspresi mengikat (tidak perlu menambahkan argumen ke metode aktual dalam model tampilan). Kemudian dalam model tampilan tambahkan kode berikut untuk "menandai" binding pada interval:

signal = 0;
attached() {
  this.interval = setInterval(() => this.signal++, 120);
}
detach() {
  clearInterval(this.interval);
}

Berikut adalah plunker yang berfungsi untuk mendemonstrasikan teknik ini: http://plnkr.co/edit/3sXQM0


Menggunakan ObserverLocator akan membutuhkan lebih banyak perubahan pada kode Anda. Anda harus menelepon var observer = observerLocator.getObserver(obj, propertyName) untuk masing-masing properti yang terikat pada nilai input. Maka Anda harus menelepon var dispose = observer.subscribe(::this.computeSums). Selanjutnya Anda harus refactor fungsi sum Anda menjadi properti yang sebenarnya sehingga computeSums dapat memperbarui nilai mereka yang pada gilirannya akan memicu penjumlahan jumlah untuk memperbarui. Akhirnya Anda harus membuang langganan dalam metode terpisah.


4
2017-10-06 10:37