I feel like my grip on reality is slightly less than it was yesterday. I can make a Polymer pass, but I have no idea why this makes it pass.
I have a very simply
<x-double>
Polymer element that takes the input of one attribute and doubles it on another attribute:<polymer-element name="x-double" attributes="in out"> <template></template> <script> Polymer("x-double", { ready: function(){ this.inChanged(); }, inChanged: function(){ this.out = parseInt(this.in) * 2; } }); </script> </polymer-element>I have a correspondingly simple Karma / Jasmine test that tries to verify the element behaves as expected:
it('works', function(){
// Container element
var container = document.createElement('div');
// Polymer element for testing
var el = document.createElement('x-double');
el.setAttribute('out', '');
el.setAttribute('in', '42');
container.appendChild(el);
document.body.appendChild(container);
// Wait for the Polymer element to update itself...
var done = false;
waitsFor(function(){ return done; });
el.async(function(){ done = true; });
// Check expectations...
runs(function(){
expect(el.getAttribute('out')).toEqual('84');
});
});
Well, maybe not that simple, but it ought to work based on all of the research that I have done for Patterns in Polymer. So, naturally, the test fails:Expected '' to equal '84'. Error: Expected '' to equal '84'. at null.<anonymous> (/home/chris/repos/angular-bind-polymer/test/BindingSpec.js:20:38)As I mentioned, I can make this pass, but only if I add a hack that I do not understand. I change the
inChanged()
watcher method to set the out
attribute in addition to setting the out
property: inChanged: function(){
this.out = parseInt(this.in) * 2;
this.setAttribute('out', parseInt(this.in) * 2);
}
But why is that necessary? Setting the property should set the attribute. Or am I crazy? I go back to read the documentation and, yes, “property values are reflected back into their attribute counterpart.” So what absolutely stupid thing am I doing tonight to prevent that from happening?Well, it turns out that what I am doing was not absolutely stupid, but it was certainly a little stupid. I failed to read the mailing list which including a message about a breaking change to—you guessed it—attribute binding. It seems that binding like this, is not a typical use-case. It is still supported, but it is opt-in now. I can live with that (though it would be nice if the docs were updated).
Anyhow, I remove the explicit setting of the attribute, and instead opt-in for property reflection. To do so, I add
reflect: true
to the published
definition for my element:<polymer-element name="x-double" attributes="in out"> <template></template> <script> Polymer("x-double", { publish: { out: {value: 0, reflect: true} }, ready: function(){ this.inChanged(); }, inChanged: function(){ this.out = parseInt(this.in) * 2; } }); </script> </polymer-element>With that, I have my test passing. And a little of my sanity restored.
Day #43
No comments:
Post a Comment