jperezov
jperezov

Reputation: 3171

Don't destroy DOM elements with #each in Ember/Handlebars

I'm trying to do a CSS animation for a bound array in ember. I'd like to do an animation each time the value changes, but it won't animate, because Handlebars completely replaces everything within the #each helper whenever the array it's iterating over changes.

Here's a simplified version of what I'm doing:

{{#each array}}
    {{custom-component value=this}}
{{/each}}

And the template for the custom-component:

<script type="text/x-handlebars" data-template-name="components/custom-component">
    <li {{bind-attr style=customAnimatedStyleThatChangesWithValue}}>{{value}}</li>
</script>

I can pre-render it with a placeholder array, e.g.:

{{#each placeholderArray}}
    {{custom-component value=[don't know what to put here]}}
{{/each}}

But, as stated in the code block, it's not like I can do value=array[this] in the custom-component call. I don't think the custom-component will re-render if the value changes, but I don't know how to pass in the value of a different array when iterating with #each.

TLDR: How can I iterate through an array of components without destroying and re-creating them whenever the array changes?

Upvotes: 1

Views: 278

Answers (1)

jperezov
jperezov

Reputation: 3171

So it seems I was on the right track before with the placholder array. Here's how I ended up solving this:

{{#each arrayPosition in placeholderArray}}
    {{custom-component value=array arrayPosition=arrayPosition}}
{{/each}}

I pass through the original array I wanted as the value in the component, and also pass through the position of the placeholder array I'm in. This lets me do the following in the controller:

App.CustomComponentController = Ember.Component.extend({
    ...
    customAnimatedStyleThatChangesWithValue: function() {
        //Grab the original array
        var valueArray = this.get('value');
        //Use arrayPosition to get the value you initially wanted to pass through
        var value = valueArray[+this.get('arrayPosition')];
        return "width: "+value+"px"; //Or whatever you're animating
    }.property('value')
});

Doing it this way makes it so that, as long as placeholderArray does not change, the custom component is not destroyed and then recreated.

Upvotes: 0

Related Questions