I want iron media query to call a function when the query matches changes and check if the query matches is true , do something ...
this is my code:
<dom-module id="example-example">
<style>
</style>
<template>
<iron-media-query query="(min-width: 200px)" query-matches="{{small}}" on-query-matches-changed="detectSmall"></iron-media-query>
<iron-media-query query="(min-width: 1400px)" query-matches="{{large}}" on-query-matches-changed="detectLarge"></iron-media-query>
</template>
<script>
Polymer({
is: 'example-example',
detectLarge: function(){
console.log(this.large);
},
detectSmall: function(){
console.log(this.small);
}
});
</script>
</dom-module>
for the first time I load the page , my device width is 1300px so this.small should be true , but it is undefined .
What exactly am I doing wrong here?
The reason is by the time your change event is fired Polymer is still not finished with the element.
If you want to access that property in your function you can use it like this
detectLarge: function(e){
console.log(e.detail.value);
},
Related
I'm using Polymer 1.0 to create a web application.
I have various elements doing one or more iron-ajax calls and I have another element for showing the loading-overlay. But in my current sollution I have added the loading-overlay, with its logic to show or not, to every element doing ajax calls.
<dom-module id="backend-call-application">
<template>
<iron-ajax id='loadA' loading="{{_loadingA}}" ...></iron-ajax>
<iron-ajax id='loadB' loading="{{_loadingB}}" ...></iron-ajax>
<loading-overlay id="loadingOverlay" with-backdrop></loading-overlay>
</template>
<script>
Polymer({
is: 'backend-call-application',
observers:[
"_isXhrLoading(_loadingA,_loadingB,....)"
],
_isXhrLoading: function() {
for (var i = 0; i < arguments.length; i++) {
if (arguments[i]) {
this.$.loadingOverlay.open()
return;
}
}
this.$.loadingOverlay.close()
}
});
</script>
</dom-module>
Now my question is, what is the best way to show such a loading-overlay?
One idea of mine would be, to have something like an observer in the loading overlay. So every element doing requests will bind its properties to the observer. These properties could be stored in an array and everytime on change, the loading-overlay checks if at least one have loading properties set to true. When one or more properties are true the loading-overlay will be opened and when all requests finished loading it will be closed.
Another idea was to use events to tell the loading-overlay when a element starts/stops loading. But here will be the problem, that I have more than one request at the same time (The first request closes the overlay, but the page hasn't finished loading).
Edit:
The loading-overlay is an element containing the IronOverlayBehavior.
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/iron-overlay-behavior/iron-overlay-behavior.html">
<link rel="import" href="../../../bower_components/paper-spinner/paper-spinner.html">
<dom-module id="loading-overlay">
<template>
<paper-spinner active="true"></paper-spinner>
</template>
<script>
Polymer({
is: 'loading-overlay',
behaviors: [
Polymer.IronOverlayBehavior
]
});
</script>
</dom-module>
use one property for loading instead of 2!!
<iron-ajax id='loadA' loading="{{_loading}}" ...></iron-ajax>
<iron-ajax id='loadB' loading="{{_loading}}" ...></iron-ajax>
bind loading value to loading-overlay with some attribute and when loading is true display loader
<loading-overlay id="loadingOverlay" is-loading="[[_loading]]" with-backdrop></loading-overlay>
so each time any ajax is made then _loading will become true so displays loader
I think the only thing you could shorten is the _isXhrLoading observer.
_isXhrLoading: function() {
if(Array.from(arguments).indexOf(true) >= 0) {
this.$.loadingOverlay.open()
} else {
this.$.loadingOverlay.close()
}
}
Having trouble getting my data to work across elements. Say I have an object "records" in my host element. It is usable in that element no problem. But when I try to spin off the view into a separate element, it no longer works.
Here's an example snippet of code. The .template part works fine but I'm not able to replicate the functionality in the child element .my-list. When I try, nothing happens.
<dom-module id="host-element">
...
<template is="dom-repeat" items="{{records}}">
<p>{{item.userName}} - {{item.number}}</p>
</template>
<my-list></my-list>
<script>
Polymer({
is: 'host-element',
ready: function() {
this.records = [
{userName: 'Bob'},
{userName: 'Sally'}
];
}
});
</script>
</dom-module>
If I try simply taking the current .template code and placing it into .my-list, it doesn't work.
I assume I need someway to bind the data into the child element, but I'm not able to figure this out. Adding a: record="{{records}}" to the tag, and then using that in the child element didn't work.
Imagine this is pretty simple, just can't find the answer in the documentation.
It's important that each element's top-level template is a plain template (not is="dom-repeat" or other specialization), otherwise, it should be straightforward:
<link rel="import" href="//polygit.org/components/polymer/polymer.html">
<i>(Requires Chrome)</i>
<host-element></host-element>
<dom-module id="my-list">
<template>
<template is="dom-repeat" items="{{records}}">
<p>{{item.userName}} - {{item.number}}</p>
</template>
</template>
<script>
Polymer({
is: 'my-list'
});
</script>
</dom-module>
<dom-module id="host-element">
<template>
<my-list records="{{records}}"></my-list>
</template>
<script>
Polymer({
is: 'host-element',
ready: function() {
this.records = [{userName: 'Bob'}, {userName: 'Sally'}];
}
});
</script>
</dom-module>
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've been trying to use Polymer for a project I'm working on. And although I enjoyed it quite a lot so far, I ran into a problem I just can't solve.
I dumped it down to a simple example. Basically it's just a list element (item-list) that contains item elements (item-card) and i want to parse the items position to the element via the attribute pos. But for some reason the items attribute is allways undefined! Is this because the attribute is bound to the variable i, which dies after the template repeat? If so, how do I work around it? Is there a different approach I should be using here?
SOLUTION: You can find the solution by reading through all the comments, but to sum it up: apperantly there was a timing issue and the attribute wasn't ready at the ready callback. But I found out about the domReady callback (polymer lifecycle documentation). Using domReady it works just fine! Thanks to Günter Zöchbauer for the help!
This is the item-list.html:
<link rel="import" href="components/polymer/polymer.html">
<link rel="import" href="item-card.html">
<polymer-element name="item-list">
<template>
<style>
</style>
<template repeat="{{values, i in data.data}}">
<item-card pos="{{i}}"></item-card>
</template>
</template>
<script>
Polymer({
created: function()
{
this.num = 123456;
this.data = { "data":
[
{
"value":999
},
{
"value":666
},
{
"value":555
},
{
"value":222
}
]
};
}
});
</script>
</polymer-element>
This is the item-card.html
<link rel="import" href="components/polymer/polymer.html">
<polymer-element name="item-card" attributes="pos">
<template>
<style>
</style>
</template>
<script>
Polymer({
ready: function()
{
console.log("ready: " + this.pos);
}
});
</script>
</polymer-element>
I didn't bother putting the index.html in, since it just containts one item-list element.
Thanks alot!!
I think you need a pos field in <item-card> in addition to the attributes="pos" declaration.
The repeated element also references the bound model which can be accessed like querySelector('item-card').templateInstance.model property.
See https://github.com/PolymerLabs/polymer-selector/blob/master/polymer-selector.html#L286 for an example.
Info:
According to the comments it turned out to be a timing issue. The value wasn't yet assigned when the ready callback was called but using domReady worked.
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>