How to access a component specific value from a nested component


#1

I was running into issues with the block params while trying to create a customisable table view.

So, first the things I was able to achieve. I created a custom-table component, which allows to provide a custom template for the row by calling like this. For the sake of simplicity, data is a parameter of the controller

application/template.hbs:

{{#custom-table model=data}}

  {{#table-row model=data as |row|}}
    <!-- custom table row template -->
    <span>custom row:</span><span>{{row}}</span>
  {{/table-row}}

{{/custom-table}}

I created a table-row component, which has a template that makes use of a block param and iterates through the model:

table-row/component.hbs:

{{#each model as |row|}}
  <div>{{yield row}}</div>
{{/each}}

This works pretty well so far. However, the custom-table component keeps all the logic for the table, like filtering data. Now I would like to enable the user to specify a custom header. However the header would for instance need to have access to the filter value from the table component. So, the custom-table component should be called like that:

{{#custom-table model=data}}

  {{#table-header}}
    <!-- custom header template -->
    <div>
      <!-- access filter value from custom-table -->
      {{input value=filter}}
    </div>
  {{/table-header}}

  {{#table-row model=data as |row|}}
    <!-- custom table row template -->
    <span>custom row: </span><span>{{row}}</span>
  {{/table-row}}

{{/custom-table}}

Apparently the filter is assumed to be found within the scope of the application template and not the custom-table component. Same issue if I would like to use the filteredData property of the custom-table component to render the rows. Is there a way to access the parameters of the custom-table component, when providing an option to use a customisable template?

Here is a twiddle showing my issues: https://ember-twiddle.com/2589e8d0f783a6ddc15c


#2

I don’t have much time so I’ll just point at this: http://emberjs.com/blog/2015/02/07/ember-1-10-0-released.html#toc_block-params

It’s not yet covered in the documentation, but it’s been around for a while, and it can be used to solve the kind of problem you’re tackling.


#3

Thanks for reply. That piece of documentation has been what I have been banging my head against for a few hours today. I can see how it is possible to pass variables from parent template to child template, but I could not figure out how that would solve my problem, as I need a variable from the component scope. But the template is defined when calling the component from the template.

<!-- data is from controller, which works fine to pass to child components -->
{{#custom-table model=data}}

  {{#table-header}}
    <div>
      <!-- I need the filter variable here, which is defined in the js part of the custom-table component and have no idea how to make that available-->
      {{input value=filter}}
    </div>
  {{/table-header}}
{{/custom-table}}

#4

Take the time to re-read it with a fresh look perhaps. The very point of block params is to pass inner data to embedded block.

The key part is the use of the {{yield foo bar}} helper, to pass foo and bar to the block: {{#my-component as |x y|}}{{x}}{{y}}{{/my-component}} will print the value of foo and bar.


#5

Ah thanks a lot. Now that makes sense. Updated the twiddle with a working version.