I'm trying to use requirejs with Polymer:
<polymer-element name="test-element">
<script>
require(['module'], function (module) {
Polymer('test-element', module);
});
</script>
<template>
Test
</template>
</polymer-element>
But I get the warning:
Attributes on test-element were data bound prior to Polymer upgrading the element. This may result in incorrect binding types.
- Should I be concerned about this warning?
- What can I do to make
attributes be data bound after Polymer upgrades the element?
- Is
there any other Polymer specific loader to load AMD modules into
polymer web components?
---------edit
It turned out that the problem occurs only if test-element is inside anouther polymer web component.
I've created a github repo to show this:
https://github.com/finalclass/polymer-bug-requirejs
EDIT: Thanks for clarifying that this only is an issue when your Polymer element is inside another Polymer element. That points to the underlying issue. It's not particular to using requirejs; you can reproduce the warning via something like
<script>
setTimeout(function() {
Polymer('test-b', {});
}, 0);
</script>
In both cases, the Polymer('test-b', ...)
function is invoked asynchronously after the parent element (<test-a>
in your example) has already been fully initialized, and that's apparently not a good practice.
You could refactor things a bit to get to something that Polymer is happy with. For instance, if module
holds a bunch of properties that you want to set on your <test-b>
, you could defer loading the module and setting them until after the created
callback has been fired, like so:
<script>
Polymer('test-b', {
created: function() {
var testB = this;
require(['test-b-js'], function (module) {
// There might be a more efficient way to copy over the properties...
Object.keys(module).forEach(function(key) {
testB.publish[key] = module[key];
});
});
}
});
</script>
This also follows the documented best practice for initializing properties that are array/objects without having to worry about shared state gotchas, so there's an added benefit. There is the slight concern that the properties won't actually be set during the created
callback but instead slightly afterwards (since, again, the callback in require()
is asynchronous), but in practice that might not be an issue.
A potentially larger concern is that those properties won't be published; if that's important to you, then a more creative solution is needed.
The discussion in Jeff's answer is right on the money. Once you defer the registration of an element in some way (e.g. setTimeout, require) you have to make sure nobody else tries to use the element before it is ready.
Another possibility is to only defer access to the module code and not block the element entirely, something like this:
<script>
(function() {
var base = null;
require(['base'], function(module) {
base = module;
});
Polymer({
get name() {
return base ? null : base.name;
}
});
})();
</script>