One-Way bounded component's properties (future proofing 1.x to 2.0)

TL;DR - A working JS Bin example.
I think that forcing yourself writing components with one-way bounded properties is a good way to prepare your code for 2.0.
I came up with a Mixin which scans for properties names that ends with the suffix "OneWay" and creates/re-defines correspondent one-way bounded props (same name, omitting the suffix) for each prop. Thus, in your component code you can refer only to the auto generated properties and change only them.
In this way the uni directional data flow can occur:
DD → AU → DD → AU → …
(* DD - Data Down, AU- Action Up)

// app/mixins/one-way-props.js

export default Ember.Mixin.create({
  oneWayPropRegExp: /^(.*)OneWay$/,
  init: function(){
    var oneWayRegexp = this.get('oneWayPropRegExp');
    this._super();
    Ember.keys(this).forEach(function(propName){
      var matches = oneWayRegexp.exec(propName),
          oneWayPropName = matches && matches[1];
      if (oneWayPropName){
        Ember.defineProperty(this, oneWayPropName, function(key, value) {
        var retValue;
        if (arguments.length > 1){
          retValue = value;
        } else {
          retValue = this.get(propName);
        }
        return retValue;
      }.property(propName));  
      }
    }, this);
  }
});

Usage:

{{!-- app/templates/application.hbs --}}

{{some-example aPropOneWay=someValue action="actOnCommit"}}
{{!-- app/templates/components/some-example.hbs --}}

{{input value=aProp}}
 <button {{action 'commit'}}>Commit</button>
// app/components/some-example.js
import OneWayPropsMixins from 'app/mixins/one-way-props';

export default Ember.Component.extend(OneWayPropsMixins, {
  actions: {
    commit: function(){
      this.sendAction('action', this.get('aProp'));
    }
  }
});

WDYT?

2 Likes

After upgrading to 1.13.x I’ve had to change

Ember.keys(this).forEach(function(propName){

to

Ember.keys(this.attrs).forEach(function(propName){

Thanks… this really is a great mixin we should all get used to using

1 Like

Thank you @albertovasquez for this correction.
Here is an updated Ember Twiddle with your correction and some more up-to-date Ember code):