How to recompute a Helper when a Model is loaded


#1

Hi,

I’m using ember-i18n in my application and my models have properties like nameEn and nameFr. To provide a generic way to access the name in the current locale, I created a helper to handles this

{{i18n-get myRecord "name" locale}}

if locale is fr it will go fetch nameFr for instance.

It works quite well when myRecord is the route’s model and is loaded but when it’s a promise, it will not recompute when the record is finally loaded.

Is there any way to create a helper that recomputes when one of its arguments is a Model/Promise? I have a hard time finding a solution about this when searching Google.

Thanks!


#2

hey, you can recompute helpers. Check here https://emberjs.com/api/ember/2.16/classes/Helper/methods/recompute?anchor=recompute

Other thing is, what you mean by “but when it’s a promise” - what is a promise ? Route model ?

Or you’re setting myRecord in other way ?

you could always use notifyPropertyChange on myRecord - that should force recompute on helper


#3

Hi @CezaryH,

I already recompute the helper when the locale changes, I’m just wondering if I can do the same when the passed model is loaded.

When I talk about a Model/Promise, it’s for instance this:

{{i18n-get house "name" locale}}

{{#each house.rooms as |room|}}
  {{i18n-get room "name" locale}}
{{/each}}

Here house is loaded by the route so getting house.nameEn in the helper works but since room are not already loaded it will print undefined.

To make things clearer, here it what the helper looks like:

import Ember from 'ember';

const { Helper, inject: { service }, isPresent, observer } = Ember;

export default Helper.extend({
  i18n: service(),

  compute([record, propertyName, locale]) {
    let definedLocal = locale || this.get('i18n.locale');        // returns "fr"
    let localeName = definedLocal.capitalize();                  // returns "Fr"
    let propertyNameWithLocale = `${propertyName}${localeName}`; // returns "nameFr"

    return isPresent(record) ? record.get(propertyNameWithLocale) : '';
  },

  _localeDidChange: observer('i18n.locale', function() {
    this.recompute();
  })
});

One idea we got was to use a component instead, even if I feel a bit dirty doing so :frowning:


#4

it look like you need notifyPropertyChange when your Promise resolves.

check here, I’ve created this simple example https://ember-twiddle.com/43541c755136c47538d1c567b1b15ecd?openFiles=helpers.my-helper.js%2C


#5

Thanks for this example. I’m not sure how to use this though. Here you’re using a timer to call the notifyPropertyChange but in our case it’s when the promise gets resolved. I think tracking each and every relationship of the model and trigger this would make for a big mess in the code :confused:

Since then we ended up using a helper to get the localized attribute name and a classic {{get to obtain it. Not the solution I was hoping for but at least it works and we got to deliver something ^^

The code looks like

{{get model (i18n-prop "name" locale)}}