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

iterate objects with #each #40

Closed
jeffrey-vella opened this issue Dec 11, 2011 · 10 comments
Closed

iterate objects with #each #40

jeffrey-vella opened this issue Dec 11, 2011 · 10 comments

Comments

@jeffrey-vella
Copy link

Currently #each only works if you have an array, so i am having to do a costly conversion:

http://jsfiddle.net/pixelhobo/E9dUm/

It would be much better you went over the key/value pairs of an object, something like this:

http://jsfiddle.net/pixelhobo/cfEnt/

@BorisMoore
Copy link
Owner

The behavior of {{#each dataExpression}} ... {{/each}} or {{each dataExpression tmpl="myTemplate"}} is to render the content of the template against the data returned by dataExpression.

If the data is an array, it iterates for each item - which becomes the current dataItem for that rendered template (view) - and concatenates the result. But if dataExpression returns a single object, then it renders just once, with that object as current data item.

If you don't pass any data at all, as in {{each tmpl="myTemplate"}} then it will render the template just once, keeping the current dataItem from the outer scope.

I am considering changing the name of the tag from each to {{for}} to make less surprising that it does not iterate when you pass it a singleton.

It is not a common scenario to render the same template against each of the properties of an object. Usually you know, statically, the properties of the object, and can do

{{#each propertiesObject }}
    Created Date: {{=createdDat}} 
    Created By: {{=createdBy}} 
{{/each}}

If you want to apply the same template to each property, as an iteration over all the properties, you can provide a helper function to return the array, rather than add a new array to your data, as in {{#each $ctx.propertyArray(properties)}}...{{/each}}

See also this comment on my blog

@BorisMoore
Copy link
Owner

See also #49

@quasipickle
Copy link

My apologies for necro-posting, but I wanted to provide an example of why someone might want to iterate through the properties of an object.

In a nutshell, for the purposes of data-linking, an array/collection does not allow (or very easily allow) for changing just one property of one entry.

Take this data:

inout = {
    joe:{
        name:  'Joe',
        status: 'out'},
    jane:{
        name: 'Jane',
        status:'in'},
    jill:{
        name:'Jill',
        status:'away'}
}

And I render it like so:
$("#domElement").link(inout,"#templateID");

I could then update a particular person like
$.observable(inout).setProperty({joe:{status:'in'}});

I think - I haven't tested this, but looking through the source, I'm guessing this is how it works

By only being able to iterate over arrays, I either need to

  1. Re-generate the entire array server side (assuming the change is triggering an ajax request to save in a DB or something), or
  2. Convert the inout object to an array, and keep a mapping of people to array index, so I can update the property like so:
    var index = nameToNameMap['joe'];
    $.observable(inout).setProperty({index:{status:'in'}});

Is there another way to approach this?

@BorisMoore
Copy link
Owner

I agree there are scenarios where this is useful. I hope to be able to look into supporting it...

@RobinDaugherty
Copy link

Can we reopen this issue then please? It's definitely necessary, and the original poster closed the ticket for some reason.

@BorisMoore
Copy link
Owner

I may provide built-in support for this in the future, but already it is quite easy to address this scenario using a custom helper function or tag. I have added a sample to show how to do that. (Code here)

@RobinDaugherty
Copy link

That looks perfect. Thanks!

@stewartlord
Copy link

Any chance of reopening this issue? It took me a while to figure out hashes are not supported by {{for}}. Cool that you can do it via custom helpers, but this seems rather fundamental.

@BorisMoore BorisMoore reopened this Feb 14, 2013
@BorisMoore
Copy link
Owner

OK, makes sense. Reopening as a feature request for built-in support.

@BorisMoore
Copy link
Owner

This feature is now supported, using the new {{props}} tag.
https://github.com/BorisMoore/jsrender/blob/master/demos/scenarios/03_iterating-through-fields-scenario.html
http://borismoore.github.io/jsrender/demos/scenarios/03_iterating-through-fields-scenario.html
#218

{{props details}}
        <div>
                <b>{{>key}}</b>: {{>prop}}
        </div>
{{/props}}

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

No branches or pull requests

5 participants