Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

template does not react to array changes #420

Closed
johan-ohrn opened this issue Apr 11, 2019 · 5 comments
Closed

template does not react to array changes #420

johan-ohrn opened this issue Apr 11, 2019 · 5 comments
Labels

Comments

@johan-ohrn
Copy link

Please see the following fiddle

What I'm trying to do is have a function execute when an array is changed observably. I.e. adding or removing elements from the array.
The example is very simple. I want to aggregate information from the array and present it. Here I have used a function on the viewmodel but it might as well have been a converter.

As demonstrated the following template expression does not pick up the observable insert:
{^{:highestNumber(array)}}
but this expression does:
{^{:array.length && highestNumber(array)}}

I assume that the thought process is that you would normally iterate over arrays such as {^for{ array}} but in my case I want to present the array by passing it through a function or a converter.

I'm able to make it work by adding .length to the template expression and this causes jsviews to re-evaluate the whole expression as a result of the length changing.

@BorisMoore
Copy link
Owner

Yes, that is by design. {^{someTag a some.b fn(c)/}} will update by default when a b or c change (property change) but will not update (be default) if a b or c is an array and there is an observable array change.

This is because usually you don't want the whole tag to refresh whenever one of the arrays changes - especially with {{for arrayA}}, which is optimized to do incremental rendering when the array changes.

So the design is largely driven by perf considerations.

On the other hand, depends paths, and observe paths do trigger changes if arrays change.

So in your sample if you write

  function highestNumber() {
    var max = 0;
    for(var i =0; i <this.array.length; i++) {
    	max = Math.max(max, this.array[i].value);
    }
    return max;
  }

  highestNumber.depends = "array"

then {^{:highestNumber()}} will update on array change. (Or you could write {^{:highestNumber() depends="array"}} so the tag declares the dependency, rather than the function.

But that said, this is not very intuitive, and as a fix for your scenario might be considered a bit hacky...

So once again your feedback has led me to some interesting considerations, and here:

jsviews_1.0.3_candidateE.zip

you will find an update which includes a new feature. On any tag, you can set onArrayChange=true and it will respond to array changes.

In your case you can write

{^{:highestNumber(array) onArrayChange=true}}`

Or you could create a custom tag

$.views.tags("mytag", {
  render: function(val) {return val;},
  onArrayChange: true
});

with

{^{mytag highestNumber(array)/}}`

Let me know if it works for you, and if you find any issues.

@johan-ohrn
Copy link
Author

johan-ohrn commented Apr 13, 2019

Would it be possible to have onArrayChange set to true by default for colon/print tags (:) such as {^{:highestNumber(array)}}. I can understand how it would be a bad idea for block tags such as {^{for}} or any other tag for that matter that have content. Given my current understanding I don't see a situation where you would include an array in a colon/print tag expression and not wanting the expression to re-evaluate if the array changes.

@BorisMoore
Copy link
Owner

BorisMoore commented Apr 15, 2019

Yes, I agree that makes sense... I had some concerns about backward compat since previously be default tags didn't observe array changes. Also we need some level of consistency between different tags. But on reflection I decided on the following approach:

By default any tag (or data-link binding) will 'observe' array changes as well as property changes. However you can set {^{foo onAfterChange=false}} on any tag or data-link expression, and you can also set it as an option onAfterChange: false on custom tags. The direct setting on the tag markup overrides the setting in the tag declaration, so you can have a custom tag which defaults to false, but has a tag instance which overrides it: {^{foo onAfterChange=true}}

Any tag which has onAfterChange set to a function (at the tag markup level or the tag declaration level) is assumed to handle its own onAfterChange behavior, so the built-in default of updating the tag whenever there is an array change will be suppressed for that tag.

So by default {^{:}} {^{>}} {^{if}} {^{include}} will observe array changes but {^{for}} and {^{props}} will not (but will use their built in incremental onArrayChange behavior). {^{on}} is also set not to observe array changes.

Here is the code: jsviews_1.0.3_candidateF.zip

@johan-ohrn
Copy link
Author

Initial testing is positive. I'll keep monitoring to see if anything shows up.

BorisMoore added a commit to BorisMoore/jsviews.com that referenced this issue Apr 28, 2019
Feature improvements:

Parens are now supported within $.observe()
  paths - e.g. "person.address().street()"

- https://www.jsviews.com/#jsvmodel@chain
- https://www.jsviews.com/#jsvviewmodelsapi@ismanagersample
- https://www.jsviews.com/#computed@observe-computed
- https://www.jsviews.com/#computed@depend-computed

Improved features for managing how tags respond to
  onArrayChange events

- https://www.jsviews.com/#tagoptions@onarraychange

New support for referencing the parent object in hierarchical
  View Model scenarios (parentRef):

- https://www.jsviews.com/#jsrmodel@parentref
- https://www.jsviews.com/#viewmodelsapi@accessparent
- https://www.jsviews.com/#jsvviewmodelsapi@ismanagersample

New support for asynchronous or batched observable change
  events (asyncObserve):

- https://www.jsviews.com/#delay

New features available for scenarios using sorting and
  filtering (mapProps and mapDepends):

- https://www.jsviews.com/#tagoptions@mapprops

Bug fixes:

- BorisMoore/jsviews#415
  (Markup within element tag - incorrect whitespace)

- BorisMoore/jsviews#417
  (Side-effect when calling Tag.updateValue during setProperty call)

- BorisMoore/jsviews#419
  (Regression: checkbox widget not working since v1.0.0)

- BorisMoore/jsviews#420
  (Template tag responses to array changes)

- Several other minor bug fixes

Additional and improved documentation topics and samples...

Updated tree view samples:
- https://www.jsviews.com/#samples/tag-controls/tree

Updated Typescript definitions (soon to be deployed DefinitelyTyped):
- https://www.jsviews.com/#typescript

Many additional unit tests...
BorisMoore added a commit that referenced this issue Apr 28, 2019
Feature improvements:

Parens are now supported within $.observe()
  paths - e.g. "person.address().street()"

- https://www.jsviews.com/#jsvmodel@chain
- https://www.jsviews.com/#jsvviewmodelsapi@ismanagersample
- https://www.jsviews.com/#computed@observe-computed
- https://www.jsviews.com/#computed@depend-computed

Improved features for managing how tags respond to
  onArrayChange events

- https://www.jsviews.com/#tagoptions@onarraychange

New support for referencing the parent object in hierarchical
  View Model scenarios (parentRef):

- https://www.jsviews.com/#jsrmodel@parentref
- https://www.jsviews.com/#viewmodelsapi@accessparent
- https://www.jsviews.com/#jsvviewmodelsapi@ismanagersample

New support for asynchronous or batched observable change
  events (asyncObserve):

- https://www.jsviews.com/#delay

New features available for scenarios using sorting and
  filtering (mapProps and mapDepends):

- https://www.jsviews.com/#tagoptions@mapprops

Bug fixes:

- #415
  (Markup within element tag - incorrect whitespace)

- #417
  (Side-effect when calling Tag.updateValue during setProperty call)

- #419
  (Regression: checkbox widget not working since v1.0.0)

- #420
  (Template tag responses to array changes)

- Several other minor bug fixes

Additional and improved documentation topics and samples...

Updated tree view samples:
- https://www.jsviews.com/#samples/tag-controls/tree

Updated Typescript definitions (soon to be deployed DefinitelyTyped):
- https://www.jsviews.com/#typescript

Many additional unit tests...
@BorisMoore
Copy link
Owner

The above changes are included in the new v1.0.3 release. (Let me know if see any issues!)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants