What's the appropriate place to override the components attributeBindings on init?


#1

I have a component {{upload-image src=foo.bar}}. When foo.bar is falsy I want to give it a different value. I setting the value in init like so:

import Ember from 'ember';

export default Ember.Component.extend({
  attributeBindings: ['src'],
  tagName: 'img',

  init: function(){
    this.set('src', 'http://www.placecage.com/40/40');
    this._super();
    this.set('src', 'http://www.placecage.com/40/40');
  },

  click: function(){
    console.log(this.get('src'));
  }
});

However it doesn’t work. The image gets rendered with the value I pass in, not the default. When I click the image it does log the placecage image. Instead if I try to override it later on say didInsertElement it works as expected:

import Ember from 'ember';

export default Ember.Component.extend({
  attributeBindings: ['src'],
  tagName: 'img',

  didInsertElement: function(){
    this.set('src', 'http://www.placecage.com/40/40');
  },

  click: function(){
    console.log(this.get('src'));
  }
});

It seems a bit silly to have it render out and only then be able to change the value causing (I presume) a re-render. What’s the appropriate place to check if src is falsy and set it to a default and get the expected results?


#2
// 1.13.x way of handling this
export default Ember.Component.extend({
  tagName: 'img',
  attributeBindings: ['src'],
  didReceiveAttrs: function() {
    if (!this.get('src')) {
      this.set('src', 'http://www.placecage.com/40/40');
    }
  }
});

example: http://jsbin.com/xuzirupenu/edit?html,js,output

The new lifecycle hooks are documented here: http://emberjs.com/blog/2015/06/12/ember-1-13-0-released.html#toc_component-lifecycle-hooks


#3

Passing in undefined to the component should be the equivalent of not declaring the attribute. If you’re passing in an object, it won’t apply the set attribute value:


#4

Okay so there’s an open issue over on Github https://github.com/emberjs/ember.js/issues/11637 where they seem to be saying that I shouldn’t set the value using the two-way data binding this way.

I suppose I should make it read from a computed property instead and choose the image through that.