简体   繁体   中英

Aurelia: Computed / Observable in repeat.for

I have some editable data in a table with sums for rows and columns to be calculated.

表的例子

As I wanted to have simpler html code, I use repeat.for to build the rows of the table. To build a sum I use a function, which was the best way I came up with until now.

Unfortunately, the sums aren't updated this way when I edit the values. Getter functions would by computed, but they can't take a parameter.

I know I could write something like ${$parent.data[y]['Q1'] + $parent.data[y]['Q2'] + ...} but this gets rather long and what's 'Q1' in this example will be something dynamic in real life. And for the sums of the columns I'll have 15 rows that have to be summed - I would prefer not having to write a sum statement in html for that.

I was looking at the observatorlocator but didn't get how I could use that for my case. I think this is a rather simple szenario so I hope there is a nice solution for something like this in 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>

When the binding-behaviors feature is released we'll be able to use the "signal" binding behavior to name the value bindings and the sum bindings. Then we'll be able to "signal" the sum bindings to refresh when the value bindings change.

In the current version of Aurelia you could add a "signal" argument to the sumY and sumQ binding expressions (no need to add the arg to the actual methods in the view-model). Then in the view-model add the following code to "signal" the bindings on an interval:

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

Here's a working plunker demonstrating this technique: http://plnkr.co/edit/3sXQM0


Using the ObserverLocator would require more changes to your code. You'd need to call var observer = observerLocator.getObserver(obj, propertyName) for each of the properties that are bound to an input's value. Then you'd need to call var dispose = observer.subscribe(::this.computeSums) . Next you'd need to refactor your sum functions into actual properties so that computeSums can update their value which would in turn trigger the sum binding to update. Finally you'd need to dispose of the subscriptions in the detached method.

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