BorisMoore / jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
http://www.jsviews.com/#jsviews
MIT License
857 stars 130 forks source link

Support dependency paths for both arrayChange and propertyChange - or for observeAll... #280

Closed BurnedToast closed 9 years ago

BurnedToast commented 10 years ago

Hi,

I want to build a application similar to a driver's log. So the user can enter:

In my model there is a array "driverLog" with multiple objects containing these informations. The user can edit, remove or add data.

At the bottom of this table I want to have a summary of the distance. That summary has to update when the user adds or remove objects from the array or when the user changes the distance-property.

So I wrote a helper function:

$.views.helpers({
  sumData: function(myArray) {
    var sum = 0;
    for (var i = 0; i < myArray.length; i++) {
      sum += myArray[i].distance;
    }
    return sum;
  }
});

This helper is getting called from my template like that:

{{:~sumData(~root.driverLog, ~root.driverLog.length)}}

It isworking for any changes to the driverLog (add / remove) itself, but if I just change the distance-value of any of these - the SUM wont get updated. I know the "depends" property for helpers - but I did not found any chance to return a path that makes the helper listening to the propertyChange-Events of the array-childs.

How can i manage this?

Here is my Jsfiddle: http://jsfiddle.net/jvwfmpya/6/


Boris showed me this thread: http://jsfiddle.net/BorisMoore/wch601L9/ The $.observable(people).observeAll(totalAmount); seems to do the trick. But I reopened this issue anyway, because I would like to know how to do this with a helper-Function? It would be great if I could define a path in my helper-dependency that does this observeall something like that:

$.views.helpers.sumData.depends = function() {
        return ["driverLog.*", "driverLog.*.*"];
};

"driverLog." for getting the arrayChanges "driverLog..*" for getting the propertyChanges of the array childs (maybe not the best syntax)

BorisMoore commented 10 years ago

I created two modified versions of your jsfiddle here http://jsfiddle.net/BorisMoore/8eqkk925/ and here http://jsfiddle.net/BorisMoore/7ewkn8L6/ - which can give some ideas as to different approaches. Notice that you don't need to make depends a function. You can write:

helpers.sumData.depends = "~recalc.count";

for a single dependency, or

$.views.helpers.sumData.depends = ["driverLog.*", "driverLog.*.*"];

for multiple paths.

On the feature request for paths corresponding to observeAll, keeping this open as a future request. Also changing the title.

Note the related request here: #158

BurnedToast commented 10 years ago

Thanks a lot Boris!

I was able to solve my problem with your first suggested workaround (http://jsfiddle.net/BorisMoore/8eqkk925/). I prefer this way over the other suggestion, because I am able to use that helper anywhere in the view - without the "logic-layer" knowing about the content of my view.

BorisMoore commented 9 years ago

Closing "After V1.0" issues for now - to reopen as appropriate.

BorisMoore commented 8 years ago

See http://stackoverflow.com/a/33484470/1054484. Syntax could be ... .depends = "lines**"; or ... .depends = "lines*.*"