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

ifelse and setProperty #298

Closed FrEaKmAn closed 9 years ago

FrEaKmAn commented 9 years ago

Hi

First of all, thank you for a really great lib. I have a problem with changing how the rendering occurs. I have attached the code http://jsfiddle.net/Lu6htmup/.

What I want to do is when I change units, that it also changes the rendering. There is an ifelseif which checks for units length and generated simple text or dropdown.

What am I doing wrong? Current code just updates the values but doesn't switch between rendering. Should I also create an ifelseif template?

Paul-Martin commented 9 years ago

When linking to an array, you want to use refresh. Additionally the {{props}} tag is more suited to enumerating properties of an object type.
See this fiddle for updates to get the desired behavior: http://jsfiddle.net/Lu6htmup/1/

Basically I changed jQuery.observable(car).setProperties('units', newunits); to jQuery.observable(car.units).refresh(newunits);

This is necessary because your if condition:

{^{if units.length === 1}}

is binding to the length property of units, not the units property. But the statement: jQuery.observable(car).setProperties('units', newunits);

replaces units with a new array. It does not update the length property of the initially bound array.

By using:

jQuery.observable(car.units).refresh(newunits);

we cause the existing array (the initially bound one) to be updated with the newunits array, and now jsviews can rerender.

I also changed your {{props}} to a simple {{for}} statement: {^{for units}}

{{/for}}

data represents the current item in a for loop. Typically we can avoid specifying #data as it is

implied, but in this case we are looping over strings and thus we want the string itself.

Hope this helps.

On Jan 29, 2015, at 11:54 AM, FrEaKmAn notifications@github.com wrote:

Hi

First of all, thank you for a really great lib. I have a problem with changing how the rendering occurs. I have attached the code http://jsfiddle.net/Lu6htmup/.

What I want to do is when I change units, that it also changes the rendering. There is an ifelseif which checks for units length and generated simple text or dropdown.

What am I doing wrong? Current code just updates the values but doesn't switch between rendering. Should I also create an ifelseif template?

— Reply to this email directly or view it on GitHub.

BorisMoore commented 9 years ago

Yes, I was about to send a quick answer with two alternatives -

first, same as Paul's suggestion:

jQuery.observable(car.units).refresh(newunits);

and second, simply change your template to use 'deep' linking:

{^{if units^length === 1}}

The deep linking syntax means you are 'listening' to both property change on the car (changing the unit property) and property change on unit (changing the length property) - and the latter is triggered by array change. But actually if you want to change to another array with the same length you probably want to use the deep linking style and and the setProperty - rather than the refresh!

Paul-Martin commented 9 years ago

Quick fiddle of the approach Boris describes:

http://jsfiddle.net/Lu6htmup/2/

On Jan 29, 2015, at 12:15 PM, Boris Moore notifications@github.com wrote:

Yes, I was about to send a quick answer with two alternatives -

first, same as Paul's suggestion:

jQuery.observable(car.units).refresh(newunits);

and second, simply change your template to use 'deep' linking:

{^{if units^length === 1}}

— Reply to this email directly or view it on GitHub.

FrEaKmAn commented 9 years ago

Wow, thanks for quick feedback. It works now!