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