I have a simple template like this
<template is="dom-repeat" items="[[items]]">
<paper-button active="{{item.selected}}" toggles raised>
<span>[[item.selected]]</span>
</paper-button>
</template>
If I activate the first paper-button in the list by tapping it and then call
this.set('items.0.selected', !this.items[0].selected);
It gets deactivated.
But then if I try the exact steps above again, the button doesn't get deactivated, which makes the button state and the selected value out of sync.
Why is it doing this? The issue can be replicated over here.
Interesting question. So I tried to use a single paper-button binding to a single item instance and it turned out to be working fine, which got me thinking that it might have something to do with path binding inside an array.
So I then added a tap handler to the paper-button and every time it's tapped, do a notifyPath on the selected subproperty path with the value of itself -
this.notifyPath('items.0.selected', this.items[0].selected);
And it works.
Related
I read carefully these threads
Polymer 1 nested dom-if within dom-repeat not updating when data changes
how to dynamically append an element to dom-if in Polymer?
How to access content of dom-if inside a custom element?
that may have some relation with my question but I didn't manage find any clue if I can do what I want and how.
In my company, there are several flows, each one for each business flow and each step of the flow is a screen coded as a Polymer 1 web component. All them are warraped in a root Polymer component which defines the route.
A simple exemple would be:
my-root-component:
<dom-module id="my-root-component">
<template>
<first-obrigatiory-page which-route={aValueReturnedFromFirstComponent}></first-obrigatiory-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromFirstComponent)]]" restamp>
<second-page which-sub-route={aValueReturnedFromSecondComponent}></second-page>
<template is="dom-if" if="[[_isTrueFunction(aValueReturnedFromSecondComponentComponent)]]" restamp>
<third-page ></third-page>
</template>
</template>
</template>
<script>
Polymer({
is: 'my-root-component',
behaviors: [doesntMatterHere],
properties: {
The first dom-if works as expected but the second seems not be taken in account and my third-page component is never showed.
I checked and the equivalent for _isTrueFunction(aValueReturnedFromSecondComponentComponent) is returning true.
Does aValueReturnedFromFirstComponent really return anything, because you should declare the attribute as which-route="{{aValueReturnedFromFirstComponent}}" instead of using simple { }.
Does the whichRoute (note the camelCase) property in the first-obrigatiory-page element have the notify: true property so the variable actually sends back the updated value?
I usually set observers on variables whenever dom-ifs don't update so I can see if they really change or not, and then set the variables myself through the console with document.querySelector('my-root-component').set('aValueReturnedFromFirstComponent', true) so I can see that the dom-if really updates.
A workaround could be to use events, but what you've done should work.
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.
How do you make dom-if templates within dom-repeat's update when the data changes??
Example here http://jsbin.com/xatala/edit?html,output
In the example the data changes after 1.5 seconds but the dom-if's inside the template aren't re-evaluated/rendered. You can see this in the console.log. The data has changed but the view isn't updated.
How would you make this work and what is the reasoning behind it?!
Here is example that works: http://jsbin.com/nejadibuju/edit?html,console,output
<template is="dom-if"
if="{{arrayItem(myItems.*, index, 'isGood')}}">
[[item.title]] is SOOO good.
</template>
What you were missing is:
Explicit bindings to array items by index isn’t supported
Some explanations are added in the Bin.
Related links:
Polymer, binding to array items not working
http://plnkr.co/edit/aOmw4e?p=preview
update 1: found this issue with pull request which seems to be addressing this issue in Polymer.
update 2: Decided to restructure my layout based on the Polymer Starter Kit which uses page.js instead of app-router, and seems to work well, although they don't use paper-item in paper-menu but instead use custom anchor elements.
Search every bit of documentation but I can't find this (although there is another issue on stackoverflow with almost the same title, not same thing)
TLDR: I need to have to whole paper-item clickable to the link. Not just the text itself. See image below for clarity and here is the live code.
.
I've got something like the code below. I'm using link tags in combination with app-router routing which works great. The only problem is: I would like to have have the entire paper-menu-item to be clickable with the link tag.
When I use below code, the right page is retrieved when clicking directly on the link tekst itself, but that doesn't create a "selected" state. When I click on the button (just off the text) then the button IS selected but the page isn't retrieved because I didn't click the link...
There must be an easy way to do this right? I mean, I could force this by overriding all the CSS but it seems to me a link in a paper-item in a paper-menu would be a very common thing which should do this automatically or with an attribute or someting?
<paper-menu class="list">
<paper-item icon="home" label="Home" ><a is="pushstate-anchor" href="/">Home</a></paper-item>
<paper-item icon="polymer" label="Demo"><a is="pushstate-anchor" href="/demo">Demo</a></paper-item>
</paper-menu>
I checked documentation on paper-item, paper-menu and others but those never use an example with a link.
IMO, the most clean way is to just drop the links altogether and just add on-tap event.
(You can also use dom-repeat for your menu)
<paper-menu class="list">
<paper-item icon="home" label="Home" on-tap="menuSelected" mypath="/">Home</paper-item>
<paper-item icon="polymer" label="Demo" on-tap="menuSelected" mypath="/demo">Demo</paper-item>
</paper-menu>
I'm assuming your are using <a> tags because of app-router.
From app-router doc:
go(path, options) - You can call the router from Javascript to navigate imperatively.
Then you can simple write your own on-tab handler and use custom attribute (mypath) on each <paper-item>
Polymer({
is: 'your-menu',
menuSelected: function (e) {
var mypath = e.currentTarget.getAttribute('mypath');
document.querySelector('app-router').go(mypath);
},
})();
Add class="flex" to each of your anchor tags.
I'm trying to scroll a simple core-list with a keyboard key.
This is the core-list:
post-list.html
<core-list data="{{posts}}" selectionEnabled="true" selection="{{selectedPost}}" on-core-select="{{selectedHandler}}" fit >
<template repeat>
<post-card post="{{model}}" index="{{index}}" ></post-card>
</template>
I need to get the index of the selected post-card, increment it and pass it to the selectItem and scrollToItem methods of the core-list.
The problem I'm facing is... how do i get the index?
I searched for an easy way to get the it both in core-list and in core-selection without success.
Unfortunately the core-list attribute "selection" from core-list is the data of the current selected record (so I can't get the index attribute from it).
Am I missing something?
Is there any solution that doesn't involve handling the index directly in the post-card component?
Thanks.
Core-list item is core-selection which handling selection event. You could try to use core-select event which you could get the index of selected item. So it could be like this
selectedHandler: function(e, detail, sender) {
var i=this.$.selection.indexOf(detail.item);
this.scrollToItem(i+1);
}