group-helper icon indicating copy to clipboard operation
group-helper copied to clipboard

Attribute binding not working properly with components inside each blocks

Open ernesto-jimenez opened this issue 11 years ago • 3 comments

Here's a quick jsbin illustrating the issue: http://emberjs.jsbin.com/migol/6/edit

You can wrap a component inside the group helper and it would work. However, if you have a group block with an each block rendering a component, the component's properties are not properly bound.

Is there any way to make this work?

I'm trying to figure out why, but I'm not familiar enough with ember's internals yet :)

Thanks!

ernesto-jimenez avatar Apr 23 '14 21:04 ernesto-jimenez

Answering myself: groupedRows=true seems to make the binding work.

I'll keep this open since, based on the documentation in the README, this seems like a side effect and not how it's intended to work.

Should this be addressed in documentation or fixed in the code?

ernesto-jimenez avatar Apr 23 '14 23:04 ernesto-jimenez

I'm using #group inside #each, because otherwise table sorting breaks. This way, component works.

denispeplin avatar May 05 '14 06:05 denispeplin

@ernesto-jimenez, groupedRows=true is the same than setup your template without the group helper, in that case, the performance improvement that brings the group helper, will not be applied.

This case is a bug in the group implementation. In your example:

  {{#each model}}
      <li>{{star-rating rating=rating}}</li>
  {{/each}}

The rating property of your component will be finally bound to _parentView.context.rating, because of the GroupedEach current implementation, the _parentView.context will be the controller content instead of a item of the content.

This problem can be easily solved when using the group helper, if the each helper is configured as:

  {{#each item in model}}
      <li>{{star-rating rating=item.rating}}</li>  
  {{/each}}

A possible fix may be to create a virtualView as a parent of the template whose context would be the array item content.

        var view = data.view;
        var childView = view.createChildView(Em.View, {
          isVirtual: true,
          tagName: '',
          _context: context,

          template: function() {
            return template(context, { data: data });
          }
        });
        data.view = childView;
        view.appendChild(childView);

However, this view addition for each item will increase the rendering time. Hopefully, someone provides a better solution for this case.

ppcano avatar May 29 '14 15:05 ppcano