mercredi 3 juin 2015

Ember.js, "modifier" property

Observe the following demo:

(app.js)

App = Ember.Application.create();

App.Router.map(function() {});

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return Ember.Object.create({
      value1: "A"
    });
  }
});

App.IndexController = Ember.Controller.extend({
  actions: {
    changeOutside: function () {
      this.set("model.value1", "B");
    }
  }
});

App.TestTestComponent = Ember.Component.extend({
  _value1: null,
  value1: function (_, newValue) {
    if (arguments.length > 1) {
      this.set("_value1", newValue);
    }
    var res = "PREFIXED " + (this.get("_value1") || "");
    return res;
  }.property(),

  actions: {
    changeInside: function () {
      this.set("value1", "C");
    }
  }
});

(index.hbs)

<h3>Inside controller</h3>
<button type="button" {{action "changeOutside"}}>Change</button>
1: {{model.value1}}<br/>
<hr />
{{test-test value1=model.value1}}

(components/test-test)

<h5>Inside component</h5>
<button type="button" {{action "changeInside"}}>Change</button>
1: {{value1}}<br/>

Working jsbin: http://ift.tt/1dLXysl

So, the idea is to have a component that can take a bound property and modify it.

As you can see in the fiddle, it doesn't works. The modified value is displayed correctly inside the component, but remains unmodified in the controller.

Playing around with modifier buttons reveals that Ember expects the property set to be the property returned, at least as far as bindings are concerned. That is, the modified value is not immediately propagated back after the "set" operation. It is only sent after the second set operation. Unfortunately, in this case, this completely breaks the illusion of "bindings just work".

Not sure if this is a bug, but I doubt it. Seems simple enough, someone would have caught it before.

The question is, how do I get this to work?

I know I can do it with two properties: "inputValue" where the controller gives its base value in and "outputValue" where it gets the modified value out (and then tie them together somehow at the controller level).

But that's super clunky. I'm sort of hoping for a more elegant solution.




Aucun commentaire:

Enregistrer un commentaire