I am having a problem accessing paper-input elements that are inside a paper-dialog. I cant seem to get the value of the paper-input while its inside the paper-dialog, I just get a return value of null. I know there is something like this.$.element but I am confused on how to actually use it. Does the paper-dialog have to be inside a self binding template?
once a paper-dialog is opened it goes into the shadowdom of core-overlay-layer scoping the elements from regular selectors. you can access it's children with the this.$.element syntax if the dialog is inside a auto-binding template
<body>
<template id="app" is="auto-binding">
// other html content
<paper-dialog id="dialog">
<paper-input id="input"></paper-input>
</paper-dialog>
</template>
<script>
(function () {
var app = document.querySelector("#app");
app.addEventListener('template-bound', function () {
this.getValue = function () {
return this.$.input.value;
};
});
}());
</script>
</body>
the other option would be to use a auto-binding template like before and create a declarative variable for the input value
<body>
<template id="app" is="auto-binding">
// other html content
<paper-dialog id="dialog">
<paper-input value="{{inputValue}}"></paper-input>
</paper-dialog>
</template>
<script>
(function () {
var app = document.querySelector("#app");
app.addEventListener('template-bound', function () {
this.getValue = function () {
return this.inputValue;
};
});
}());
</script>
</body>
a way to get around using the auto-binding template would be to put the dialog in a custom element and enclose all it's functionality there that would allow you to use either of these methods.
i hope this helps.
Related
I'm trying to observe added and removed dom nodes to my custom Polymer element without success. I've noticed that the this.$ is an empty object.
Polymer({
is: 'dramatic-view',
attached: function () {
this._observer = Polymer.dom(this.$.contentNode).observeNodes(function (info) {
console.log('kromid info', info);
});
}
});
The callback is being called only once (even tho I change content afterwards) with the following strange parameters:
I was following the docs here.
this.$ is a hash of elements in your template that have an id attribute (see Automatic node finding).
So, for this.$.contentNode to exist, you need an element with id="contentNode" in your <dom-module>'s <template>, and it must not be inside a dom-if or dom-repeat template:
<dom-module id="x-foo">
<template>
<content id="contentNode"></content>
</template>
</dom-module>
Nodes created dynamically (i.e., those inside dom-if or dom-repeat) must be queried with this.$$() (e.g., this.$$('#contentNode')). If you're trying to set them up in the attached callback, you'll need to wait until after the nodes are stamped, which could be observed with Polymer.RenderStatus.afterNextRender().
<dom-module id="x-foo">
<template>
<template is="dom-if" if="[[useDynamicContent]]">
<content id="contentNode"></content> <!-- unavailable to this.$ -->
</template>
</template>
<script>
Polymer({
is: 'x-foo',
attached: function() {
Polymer.RenderStatus.afterNextRender(this, function() {
var contentNode = this.$$('#contentNode');
if (contentNode) {
contentNode.observeNodes(...);
}
});
}
});
</script>
</dom-module>
To trigger the node observer, use Polymer's DOM API like this:
Polymer.dom(this).appendChild(node);
Polymer.dom(this).removeChild(node);
codepen
UPDATE It seems you're integrating Polymer with Elm, and expecting to see the observer callback for node-changes made my Elm. You'll need to hook Elm's calls to appendChild/removeChild somehow so that it uses Polymer's DOM API.
I'm learning Polymer. I have a view that is setup like this:
my-view.html
<dom-module id="my-view">
<template>
<template is="dom-if" if="[[ areAvailable ]]">
<my-component id="myComponent"></my-component>
<button type="button" on-click="onButtonClick">Test</button>
</template>
<template is="dom-if" if="[[ !areAvailable ]]">
<div>Move along</div>
<template>
</template>
<script>
Polymer({
is:'my-view',
properties: {
areAvailable: Boolean
},
onButtonClick: function() {
this.$.myComponent.test();
}
});
</script>
</dom-module>
This view shows my-component based on the areAvailable flag. If a user clicks the "Test" button, I need to execute a function in my-component. my-component is setup like this:
my-component.html
<dom-module id="my-component">
<template>
<h1>hello there!</h1>
</template>
<script>
Polymer({
is:'my-component',
test: function() {
alert('voila!');
}
});
</script>
</dom-module>
My challenge is, my approach works IF my-component is not inside of an "if" template. When my-component is inside of an "if" template, I get an error that says:
TypeError: Cannot read property 'test' of undefined
What am I doing wrong?
Note: Nodes created dynamically using data binding (including those in dom-repeat and dom-if templates) are not added to the this.$ hash. The hash includes only statically created local DOM nodes (that is, the nodes defined in the element’s outermost template).
Source: https://www.polymer-project.org/1.0/docs/devguide/local-dom.html#node-finding
Since you have already added a listener to the click event on your button, you can redefine that listener like this:
Polymer({
...
onButtonClick: function() {
// The this.root here refers to the local dom
// It is highly advised that you use Polymer.dom(<node>) when doing dom manipulations
Polymer.dom(this.root).querySelector('#myComponent').test();
}
});
Polymer have this simple function...
this.$$('#myComponent')
https://www.polymer-project.org/1.0/docs/devguide/local-dom#node-finding
I'm using polymer 0.8 which I understand has a new API, but I can't find a reference to this issue anywhere. I'm trying to accomplish this:
<center-focusable>
<template is="x-autobind">
<span on-click="setFocus">test?</span>
</template>
</center-focusable>
Which errors out with:
[span].[click]: event handler [setFocus] is null in scope ()
My element is defined as such:
<dom-module id="center-focusable">
<template>
<span on-click="setFocus">I work</span>
<content></content>
</template>
</dom-module>
<script>
Polymer({
is: "center-focusable",
setFocus: function () {
console.log("test");
}
});
</script>
Is this not possible?
What I've ended up doing is to defined another custom element that will trigger a custom event for me to catch.
<dom-module id="focusable-element">
<content></content>
</dom-module>
<script>
Polymer({
is: "focusable-element",
listeners: {
'click': 'setFocus'
},
setFocus: function () {
this.fire("center-focusable:center");
}
});
</script>
Then I'll catch it:
<script>
Polymer({
is: "center-focusable",
listeners: {
'center-focusable:center': 'setFocus'
},
setFocus: function (e) {
e.stopPropagation();
console.log("test");
}
});
</script>
Together:
<center-focusable>
<focusable-element>
This works.
</focusable-element>
</center-focusable>
Seems like an unnecessary amount of effort to handle this way though.
<span> is a regular HTML element, not a polymer element.
on-click is a polymer syntax.
I think you should use a regular html event : onclick (no dash).
Ex : <span onclick="console.log('test')">I work</span>
When I try document.querySelector('core-drawer-panel').togglePanel() in the console it works but when I do the following core-drawer-panel is not ready yet?
<template>
<core-drawer-panel forceNarrow>
</core-drawer-panel>
</template>
<script>
document.addEventListener('polymer-ready', function() {
document.querySelector('core-drawer-panel').togglePanel()
console.log('polymer-ready');
});
</script>
Note that I can not wrap it in a polymer element due to issues with other js frameworks.
try this
var template = document.querySelector('template');
template.addEventListener('template-bound', function () {
//code
});
with your element inside a template you need to look for template to be ready not polymer.
I am working on a Polymer project and I a few custom elements nested. For example, I have a custom element called <example-main>. Suppose that this element has a function called displayMessage()
I have another custom element defined inside <example-main> called <example-alerts>. I want the alerts element to be able to use the function in its parent, main, to display a message.
To achieve this, I am trying to select the element <example-main id='mainEl'> by using the Polymer's Automatic Node Finding hash, this.$.mainEl and using the function like so: this.$.mainEl.displayMessage();
However, I get this error message:
Uncaught TypeError: Cannot read property 'displayMessage' of undefined
Am I making a wrong approach of having Polymer elements call functions in other Polymer objects?
To visualize things a little better, the index.html would look something like:
...
<body>
<example-main id='mainEl'></example-main>
</body>
...
while example-main.html looks something like:
<polymer-element name='example-main'>
<template>
...
<example-alerts>
</template>
<script>
Polymer(example-element, {
displayMessage: function(){
//do message showing magic
}
});
</script>
</polymer-element>
and lastly, example-alerts.html looking like:
<polymer-element name='example-alerts'>
<template>
...
<paper-button on-tap='{{callFunction}}'></button>
</template>
<script>
Polymer(example-alerts, {
callFunction: function(){
//call the function in parent
this.$.mainEl.displayMessage();
}
});
</script>
</polymer-element>
You are not doing this correct way , you cannot find nodes this way .
Node finding just search within same element defined in elements outermost template.
You should either change your approach or you can use events to handle the situation pls see the sample demo which can work for you.
<polymer-element name='example-alerts'>
<template>
...
<paper-button on-tap='{{callFunction}}'></button>
</template>
<script>
Polymer(example-alerts, {
callFunction: function(){
//call the function in parent
this.fire('ouch', {msg: 'That hurt!'});
}
});
</script>
</polymer-element>
--Second Element
<polymer-element name='example-main'>
<template>
...
<example-alerts on-ouch='{{displayMessage}}'>
</template>
<script>
Polymer(example-element, {
displayMessage: function(){
//do message showing magic
}
});
</script>
</polymer-element>