Computer properties between Components


#1

I was thinking of having a child component witha property that has a oneWay relationship to a parent property like this:

isSelected: Ember.computed.oneWay(‘FilterOptionsComponent.hasSelectAll’)

I can’t get it to seem to work though. Here’s my parent component:

<script type="text/x-handlebars" id="components/filter-options">
      <h2>{{input type="checkbox" checked=hasSelectAll}} Filter Options</h2>
</script

I imagine its how I’m referencing it in the oneWay call. I’ve also tried:

isSelected: Ember.computed.oneWay(‘components/filter-options.hasSelectAll’)

and

isSelected: Ember.computed.oneWay(‘filter-options.hasSelectAll’)

Any ideas?


#2

If the parent is the enclosing component, and the child component is rendered through the parent’s {{yield}} helper, then the child should have access to properties in the parent component via parentView. There’s an outstanding proposal to rename this to parentComponent for components.

Allow the parent template to wrap the child components:

<script type="text/x-handlebars" id="components/filter-options">
      <h2>{{input type="checkbox" checked=hasSelectAll}} Filter Options</h2>
      {{yield}}
</script>

Then make use of the templates like this:

{{#filter-options}}
     {{filter-option ...}}
     {{filter-option ...}}
{{/filter-options}}

And then in the child controller:

parentHasSelectAll: Ember.computed.oneWay('parentView.hasSelectAll')

#3

The child component doesn’t need to be rendered inside a {{yield}} to have access to the parentView. The scoping alone determines this.

Also, will {{yield}} work inside an {{#each}} block? I currently define my template like this:

{{filter-options filterOptions=filterOptions selected=selectedFilters}}

 <script type="text/x-handlebars" id="components/filter-options">
     <h2>{{input type="checkbox" checked=hasSelectAll}} Filter Options</h2>
     {{#each filterOptions}}
        {{filter-option name=name optionID=id PA_toggleSelected="toggleSelected"}}
     {{/each}}
 </script>

<script type="text/x-handlebars" id="components/filter-option">
  <label>{{input type="checkbox" checked=isSelected}}{{name}}</label>
</script>

#4

Oh I see. I don’t think you could put {{yield}} inside an each block, because yield is an outlet for content between the open and close component tags. It is only yielded once.

However, I’m curious why you’re passing filterOptions as an array into the parent, and then using #each in the parent template to create the child components. Does filterOptions always come from a controller property? If you want to the component to be more flexible, so that you can declare options right in your templates, then you could put each within the yield like this:

 <script type="text/x-handlebars" id="components/filter-options">
     <h2>{{input type="checkbox" checked=hasSelectAll}} Filter Options</h2>
     {{yield}}
 </script>

<script type="text/x-handlebars" id="components/filter-option">
  <label>{{input type="checkbox" checked=isSelected}}{{name}}</label>
</script>

<script type="text/x-handlebars" id="index">
  {{#filter-options}}
    {{filter-option name="Hardcoded example option 1"}}
    {{filter-option name="Hardcoded example option 2"}}
    {{#each filterOptionsFromController}}
      {{filter-option name=name optionID=id PA_toggleSelected="toggleSelected"}}
    {{/each}}
  {{/filter-options}}
</script>

#5

In my case it does always come from the controller. The filters will depend on the model and will never change. I’ve changed it now to actually to be wired up in the component itself as to keep the template nice and agnostic from my user’s perspective. Thanks for your insight friend.