2
votes

I'm trying to extend some behaviour of Ember.TextField. I'm trying to add some logic for type="datetime-local" inputs, to be able to bind date-typed variables directly.

As we know, input values are strings, not dates. So in my new class that extends Ember.TextField I need a new property to be bound to the input that is basically a date converted to a string that the input expects. Ideally I would like to reopen Ember.TextField and then only apply this logic if the input type is datetime-local and the bound value is a Date.

My question is:

Is there any way to change an attribute binding defined in a superclass? If it were possible I could just write attributeBindings:['value:textValue'] in my View/Component subclass. This would override the previous value binding definition from Ember.TextField.

X-reference: https://github.com/emberjs/ember.js/issues/10176

2
why can't you just have a property on your view that is bound to the value of the text field? It will be a string, and you can have an observer that is observing this value, and sets the corresponding model/controller property (which needs to be a date) after converting the string to a JS Date object? Is there some reason why this won't work? - Hrishi
I wanted to use {{input value=model.startDate}}, just like I would do with an ordinary input. The problem is that I want the property to be named value to use the input helper normally. - miguelcobain

2 Answers

2
votes

Whilst not the most maintainable path to walk, you can remove and add attribute bindings manually on the init event in a view. Here is a working JS Bin.

Just treat attribute bindings as an ember array and use addObject and removeObject with the full binding string (e.g. value:testValue as the method's argument):

App.SomeView = Em.View.extend({
  attributeBindings: ['value:testValue']
});

App.ModalView = App.SomeView.extend({
  attributeBindings: ['role'],
  testValue: 'hello', // Could be on either class
  role: 'dialog',

  removeBindings: function() {
    // role stays bound, value doesn't
    this.get('attributeBindings').removeObject('value:testValue');
  }.on('init')
});

Again, here is a working JS Bin.

1
votes

attributeBindings is a "concatenated property" which means it's an array which picks up and combines values from every class on the inheritance chain, including mixins. According to a cursory reading of the Ember code, it appears that entries made "lower" on the chain are placed earlier in the concatenated array. When the element is constructed, attribute bindings are executed in order, meaning that earlier (lower, yours) attributes are overridden by later (higher, theirs) ones.

Depending on your point of view, you might call this a bug.

Let's say a higher (more super) class says att1: val1, and a lower (less super) class down the chain says att1: val2. Then val1 will "win".

The alternative to changing the attribute value used for att1 is simply to redefine val1 in your subclass, and it will be picked up properly.