0
votes

I am using JsViews to render a list, but first passing the list through a helper function like so:

<ul>
  {^{for ~filter(list, 'xyz')}}
    <li>...</li>
  {{/for}}
</ul>

Where filter creates a new list based on list with only some of the original elements based on the filtering criteria. The trouble is, when I update list:

$.observable(data.list).insert(list.length, { ... });

the {^{for ...}} does not get re-evaluated. However, if I remove the filter, changing the {^{for ...} to this:

{^{for list}}
  ...
{{/for}}

Then everything works as expected. Is there a way to achieve what I'm after? It seems JsViews should be able to do what I want, because this answer is similar enough: JsViews: Converter before helper function in data-link.

2
Now I'm wondering: is there a way to get this to work or am I going to have to invalidate part of the view to get it to re-render? $.view(this).___(...)?Jrop

2 Answers

2
votes

@Jrop: For now, your workaround makes sense. Your scenario relates to some future features of JsObservable, for having linked arrays with a transformation (e.g. filter, sort, or page) defining the relationship between the source and target arrays. The target would raise array change events whenever its content changes as a result of observable changes in the source.

Current observable APIs should make this possible to implement today, but a semi-declarative approach out of the box, in JsViews, is not yet available.

Another approach could be a derived {{for_with_filtering ...}} tag, derived from {{for}} but where you can optionally include a filter: {{forplus list filter=~filter('xyz')}}. I'll be posting a related sample very soon showing a {{for}} which lets you set the start and integers for the iteration. ({{for_range ...}}).

0
votes

Okay, so I found a workaround to this, although I sure would like @BorisMoore to weigh in on this!

The solution is to update the view manually, because the filtered data does not === the bound data (I guess). So instead of doing:

$.observable(data.list).insert(data.list.length, item);

I changed to:

data.list.push({...});
$.view('#target', true, 'data').refresh();

Where #target is the selector of the target <div> that holds the rendered content.

Again, I really would be glad if @BorisMoore could weigh in on this, as this solution refreshes a chunk of the view instead of incrementally adding an item (from what I understand).