Custom for-loop helper for EmberJS/HandlebarsJS

2019-02-16 02:41发布

问题:

A small two hours ago I started: Nested HandlebarsJS #each helpers with EmberJS not working

Shortly after I figured an acceptable temporary solution myself, question is still unaswered. My problems didn't stop there though.

I am now trying to make a custom helper which will loop through an array of objects, but exclude the first index - pretty much: for(i = 1; i < length; i++) {}. I've read on websites you have to get the length of your context and pass it to options - considering your function looks like: forLoop(context, options).

However, context is a string rather than an actual object. When you do a .length, you will get the length of the string, rather than the size of the array. When I pass that to options, nothing happens - not too mention browser freezes.

I then first tried to do a getPath before passing it to options, this returns an empty string.

What am I supposed to do instead, I made the for-loop code before for just HandlebarsJS and that worked, but EmberJS doesn't seem to take it, why?

EDIT: I pretty much also followed: http://handlebarsjs.com/block_helpers.html -> Simple Iterators

回答1:

I solved this myself after trying for a long time.

The HandlebarsJS method (as described on the site) is no longer valid for EmberJS, it's now as follows:

function forLoop(context, options) {
    var object = Ember.getPath(options.contexts[0], context);
    var startIndex = options.hash.start || 0;

    for(i = startIndex; i < object.length; i++) {
        options(object[i]);
    }
}

Heck, you could even extend the for-loop to include an index-value!

function forLoop(context, options) {
    var object = Ember.getPath(options.contexts[0], context);
    var startIndex = options.hash.start || 0;

    for(i = startIndex; i < object.length; i++) {
        object[i].index = i;

        options(object[i]);
    }
}

This is a working for-loop with variable start index. You use it in your templates like so:

{{#for anArray start=1}}
    <p>Item #{{unbound index}}</p>
{{/for}}


回答2:

Here is how I did it (and it works !!!)

First, i had in my model a 'preview' property/function, that just return the arrayController in an array :

objectToLoop = Ember.Object.extend({ 
        ...
    arrayController: [],
    preview: function() {
        return this.get('arrayController').toArray();
    }.property('arrayController.@each'),
        ...
});

Then, I add a new Handlebars helper :

Handlebars.registerHelper("for", function forLoop(arrayToLoop, options) {
    var data = Ember.Handlebars.get(this, arrayToLoop, options.fn);

    if (data.length == 0) {
        return 'Chargement...';
    }

    filtered = data.slice(options.hash.start || 0, options.hash.end || data.length);

    var ret = "";
    for(var i=0; i< filtered.length; i++) {
        ret = ret + options.fn(filtered[i]);
    }
    return ret;     
});

And thanks to all this magic, I can then call it in my view :

<script type="text/x-handlebars"> 
    <ul>
        {{#bind objectToLoop.preview}}
            {{#for this end=4}}
                <li>{{{someProperty}}}</li>
            {{/for}}
        {{/bind}}
    </ul>
</script>

And that's it.

I know it is not optimal, so whoever have an idea on how to improve it, PLEASE, make me know :)