I'm just getting started with building web-components with polymer, and was following the tutorial.
I'm just at the start, and am adding my component to my page via a script, but my html from my template isn't being displayed.
Here's what I've got so far.
document.addEventListener("DOMContentLoaded", function() {
if(!window.Polymer){
var poly = document.createElement('script');
poly.src = "http://cdnjs.cloudflare.com/ajax/libs/polymer/0.3.4/platform.js";
document.head.appendChild(poly);
}
var template = document.createElement('link');
template.setAttribute("rel", "import");
template.setAttribute("href", "http://localhost:8081/first-widget.html");
document.body.appendChild(template);
var widget = document.createElement('my-widget');
document.body.appendChild(widget);
setTimeout(function(){
Polymer('my-widget');
},1000);
});
My widget is
<polymer-element name="my-widget">
<template>
<h1>This is from the Polymer</h1>
</template>
</polymer-element>
My understanding is that this should display the content of my html from the template in my my-widget tag. I've got the localhost:8081 serving the content of the template via CORS, so that isn't the issue, and I can see the template loaded into chrome via the element inspector. So I'm not sure why I'm not getting my content.
Is there a way I need to bootstrap polymer?
In your widget, you need to import polymer.html and either use the noscript attribute:
<link rel="import" href="path/to/polymer.html">
<polymer-element name="my-widget" noscript>
<template>
<h1>This is from the Polymer</h1>
</template>
</polymer-element>
or register your element:
<link rel="import" href="path/to/polymer.html">
<polymer-element name="my-widget">
<template>
<h1>This is from the Polymer</h1>
</template>
<script>
Polymer({});
</script>
</polymer-element>
More information on creating elements: http://www.polymer-project.org/docs/start/creatingelements.html
You'll need to run your html into a server.
I'm using http-server that is very simple.
npm install http-server
Basically you navigate through to index.html file and run "http-server".
Hope it helps
It turns out I was including the platform.js but not polymer.js
If anybody is loading polymer dynamically as I am (as we're building a widget which other people can include in their page), it seems it is best to use the noscript attribute as #pikanezi described, as you don't run into timing issues this way.
Related
Given this simplified component:
<dom-module id="poly-component">
<template>
<paper-button raised onclick="dialog.open()">Button</paper-button>
<paper-dialog id="dialog"><h1>Paper Dialog Here!</h1></paper-dialog>
</template>
<script>
Polymer({
is: 'poly-component'
})
</script>
which does nothing more than open the dialog on clicking the button.
This module works when it used once on a page.
But when it is inserted twice
[...]
<dom-module id="polyTest-app">
<template>
<h2>Hello [[prop1]]</h2>
<poly-component></poly-component>
<poly-component></poly-component>
</template>
[...]
it doesn't work anymore.
A click on the button leads to a:
(index):1 Uncaught TypeError: dialog.open is not a function
Am I missing something?
The code for this example can be found here: Example Code on GitHub
Your code cannot work because you're not binding the event handler correctly.
A built-in handler like onclick tries to execute the bit of code in global scope where dialog doesn't exist. Hence the error.
Here's how you can rewrite your code
<dom-module id="poly-component">
<template>
<paper-button raised on-click="_dialogOpen">Button</paper-button>
<paper-dialog id="dialog"><h1>Paper Dialog Here!</h1></paper-dialog>
</template>
<script>
Polymer({
is: 'poly-component',
_dialogOpen: function() {
this.$.dialog.open();
}
})
</script>
</dom-module>
First, notice how onclick changes to on-click - the Polymer event handling notation. PS. tap event is advised.
Second, you can only access other elements from code. Not directly in bindings. Hence the _dialogOpen function.
UPDATE
Ok, I know what's happening. When there is only one element with a given id, the browsers let's you use it simply by that id in global scope.
When you use Shady DOM, which I assume you do, two instances of your poly-component element render two <dialog id="dialog">. At this point window.dialog is not available anymore.
Again, with Polymer it's safer to use the this.$ notation aka Automatic node finding to reference elements in local DOM.
I just started using polymer for creating web-components.
When I import only one custom element everything is fine.
Now I want to use the polymer element iron-collapse in my custom web component and I want to import both of them in my HTML.
<link rel="import" href="../custom-accordion.html">
<link rel="import" href="../bower_components/iron-collapse/iron-collapse.html">
Both of the elements are positioned inside a dom-module Tag in their files:
<dom-module id="custom-accordion">
....content
</dom-module>
and
<dom-module id="iron-collapse">
....content
</dom-module>
When I want to import both I get the error :
Uncaught NotSupportedError: Failed to execute 'registerElement' on 'Document': Registration failed for type 'dom-module'. A type with that name is already registered.)
I think I have to use this dom-module tag in both, otherwise I can't create my web-component. Right?
Any ideas how to solve this issue?
dom-module is Polymer. The issue is polymer is running twice and trying to register dom-module element. In your code you are just using the dom-module element.
I am not sure how you are running your solution. Try below and see if it works
If you have included polymer in index.html, try removing it.
Try using polymer-starter-kit as your start. It takes care of most of these issues and comes packed with all the tools required to build a production ready polymer application. You can just focus on your code.
Do you have a Polymer-element in a script-tag inside your dom-module? You need to rename this as well :
<dom-module id="**yourElementName**">
<template>
[...]
</template>
<script>
Polymer({
is: "**yourElementName**",
[...]
})
</script>
</dom-module>
What is the best practice for linking a script to the index.html in polymer. I have a menu on in my index file and what to use dom-if to hide certain buttons depending on the users permission. That permission check uses ajax(iron-ajax). I am unsure how to link Polymer({}), to the index, as the index is not a custom element.
<template is="dom-bind" id="app">
<template is="dom-if" if="{{myProp}}">
</template>
</template>
<script>
var app = document.querySelector('#app');
app.myProp = true;
</script>
I want to use Polymer's UI elements (e.g., iron-icons, paper-button, etc.) without making custom elements or templates.
For example, let's say I have:
<paper-button id="my-button">Click me</paper-button>
How do I listen for the 'click' event? Simply adding an event listener to 'click' for the ID 'my-button' doesn't work.
It should just work? I'm assuming you want to use Polymer UI elements in the main doc (index.html) without having to create any custom components. Say you have
<paper-button id="btn">Click me</paper-button>
in index.html. Via vanilla js,
document.querySelector("#btn").addEventListener("click", function (e) {...});
and via jQuery,
$("#btn").on("click", function (e, u) {...});
p/s: I'd write a quick jsbin as a demo, but rawgit seems to be having issues, and I'm not aware of alternative CDNs that host Polymer Elements.
Let me be clear: Polymer elements, and by extension web components, are designed to be framework-agnostic and, if properly coded, will work on their own - just like any other HTML element. Please do not dom-bind for the sake of dom-binding. You only do so if you a) require Polymer's sugaring (like data-binding) in your use-case; and b) you want to use Polymer's sugaring from your index.html - if you don't, please don't add additional complexity to your app.
I've found a cdn serving polymer elements, so:
Look, no dom-bind and elements are working with vanilla js.
Look, no dom-bind and elements are working with jQuery.
You can try:
<template is="dom-bind" id="t">
<paper-button id="my-button" on-click="buttonClicked">Click me</paper-button>
</template>
<script>
var template = document.querySelector('#t');
template.buttonClicked= function () {
alert("he clicked me :)");
};
</script>
$( "body" ).delegate( "#my-button", "click", function() {
alert();
});
I'm building an application with Polymer, and I'm having trouble creating my own component. The component I'm building is a login prompt.
<link rel="import" href="/static/bower_components/polymer/polymer.html">
<link rel="import" href="/static/bower_components/paper-button/paper-button.html">
<link rel="import" href="/static/bower_components/paper-input/paper-input.html">
<polymer-element name="login-prompt" attributes="">
<template>
<paper-input label="Email"></paper-input>
<paper-input label="Password" type="password"></paper-input>
<paper-button label="Login" affirmative></paper-button>
</template>
<script>
Polymer({});
</script>
</polymer-element>
But the moment I import more than one dependency (in this case paper-button and paper-input, I get this error in the console:
Error: DuplicateDefinitionError: a type with name 'core-meta' is already registered
It's coming from platform.js. Why is this error appearing? The demos in the documentation work exactly the same, but they behave normally.
Edit: Updated to load with absolute URLs, but I'm still getting the same error.
All righty, I figured it out. In my layout file, I was importing core-component-page. That file contains a definition for core-meta, along with some other elements that are already satisfied dependencies. I'm not sure why I had that in there, but I'd sure like to know what core-component-page is, and why it exists.