belgoros
belgoros

Reputation: 3908

Ember helper has undefined values

I can't figure out why the helper I created in app/helpers/shop-name.js:

import { helper } from '@ember/component/helper';

export function shopName(shop) {
  return shop.identifier + '-' + shop.name;
}

export default helper(shopName);

doe not format the values as needed in my template application.hbs:

<select>
  {{#each model as |shop|}}
    <option value={{shop.id}}>{{shop-name shop}}</option>
  {{/each}}
</select>

I get undefined-undefined displayed in my select list.

If I do the same conversion directly in the template:

<option value={{shop.id}}>{{shop.identifier}}-{{shop.name}}</option>

it works as needed. What's wrong with that helper ?

I'm using Ember 3.0. Thank you.

Upvotes: 0

Views: 408

Answers (2)

jelhan
jelhan

Reputation: 6338

There are multiple issues in your code.

  1. shop is an object and I bet it's an Ember.Object. If dealing with Ember.Objects, you should always use get() method to retrieve values for now. This might change soon. Since you are not using get() method, you get undefined. Embers template engine is using getter and therefore it's a huge difference between shop.identifier in your helper and {{shop.identifier}} in your template. Resolve the issue by shop.get('identifier') or import { get } from '@ember/object'; [...] get(shop, 'identifier'); Use the last one if you can't be sure that shop is an instance of Ember.Object.

  2. Since you are passing shop and not shop.identifier as argument to your helper, the helper will only be recomputed if the reference of shop changes (e.g. replaced by another object). Changes to the value of it's properties will not recompute the helper.

One solution for you problem is to use a computed property as suggested by ctcpip. Another one is the concat helper: {{concat shop.identifier '-' shop.name}}.

Upvotes: 1

Chris de Almeida
Chris de Almeida

Reputation: 458

I'm not sure that helpers can take inputs that aren't strings. I hope someone can confirm.

Anyway, your use case is really better handled at the model level, using a computed property:

shopName: computed('identifier', 'name', function() {
  return `${identifier} - ${name}`;
})

and then you would just use {{shop.shopName}} in your template

Upvotes: 1

Related Questions