1

I've just started learning Ember and one thing I'm confused that if I can access component's method inside the template.

For example, I have a note-list component that render list of note-line as follow:

<ul class="list">
  {{#each notes as |note|}}
    {{note-line note=note index=@index selected=(isSelected note)}}
  {{/each}}
</ul>

The note-list component is defined as:

Ember.Component.extend({
    tagName: '',
    isSelected(note) {
        return note.id === this.get('selectedNote').id
    }
})

But I'm getting error Assertion Failed: A helper named 'isSelected' could not be found.

I think I could solve it with helpers, but it seems to be not a good solution to create a separate helper for a behaviour of a specific component.

Please help to advise me some better way to deal with it.

Thanks very much.

VinhBS
  • 677
  • 8
  • 17
  • Can you add the router part related to notes? There is a way of doing this via the `link-to` helper and a custom `activeClass`, that way you would let ember handle it instead of looping over the model and setting the property on each record. – Patsy Issa Aug 26 '15 at 09:33

1 Answers1

5

In your case, your component can determine itself if it is selected or not. Indeed, you have a function isSelected that returns a boolean whether the note-line is selected or not.

You must consider using a computed property to achieve this.

The note-line component would be defined like :

Ember.Component.extend({
    tagName: '',
    note: null,
    isSelected: Ember.computed('note', function() {
        return this.get('note.id') === this.get('selectedNote.id')
    })
})

Then, in your component template, isSelected is available as a simple component variable and is updated when note is updated.

Finally, you can simply use your component like this :

<ul class="list">
  {{#each notes as |note|}}
     {{note-line note=note index=@index}}
  {{/each}}
</ul>

But in this case, as you pointed out in your comment, you would need to pass selectedNote to each component in order for them to update the isSelected property.

One way to do this would be to have a isSelected property in the model itself as documented here. In your model function inside your route, you will just have to set this property like this :

model: function() {
    return this.store.find('notes')
     .then(function(notes) {
          notes.forEach(function(note) {
            note.set('isSelected') = true || false; // here will be implemented your function to determine if note is selected or not 
          });
          return notes;
        })
    })
}

Then in your component template, isSelected is available in note like any other attribute.

Patsy Issa
  • 11,113
  • 4
  • 55
  • 74
dynamic_cast
  • 1,075
  • 1
  • 9
  • 23
  • Thanks for your answer, but in this case it seems like I need to pass the selectedNote into to `note-line`, i.e. `{{note-line note=note index=@index selectedNote=selectedNote}}` I wonder if there's other ways to do it without passing the selectedNote, as the `note-line` actually only care about the note it show and if this note is selected. – VinhBS Aug 26 '15 at 07:57
  • 2
    I understand better what you want. Please see my updated answer. – dynamic_cast Aug 26 '15 at 08:40