iron-list inside custom element with polymer starter kit - polymer

I'm using Polymer Starter Kit as a base for an app.
So, this is a single page app with routing to specific section.
My index is basically unchanged, you can see it here https://github.com/PolymerElements/polymer-starter-kit/blob/master/app/index.html.
Now I have my custom element here
<dom-module id="lista-contatti">
<template>
<iron-ajax url="../../api/get_contacts.php" last-response="{{data}}" auto></iron-ajax>
<iron-list items="{{data}}" as="item" id="list">
<template>
<paper-icon-item>
<avatar class$="[[item.classe]]" item-icon></avatar>
<paper-item-body two-line>
<div><span>[[item.nome]]</span> <span>[[item.cognome]]</span></div>
<div secondary><span>[[item.tipo]]</span></div>
</paper-item-body>
</paper-icon-item>
</template>
</iron-list>
</template>
</dom-module>
This works because if I give a fit class to my iron-list I can see my list populating. The only problem is that my list will render under my main app header (and that makes sense because of the fit layout given to my list).
Also, the list works great with header if I put it on a single html file, as you can see in iron-list official demo pages.
Now I want to keep my list in an external dom-module, but I need it to work seamlessly with other elements of the page in the single page app scenario of the polymer starter kit.
EDIT: this is my index.html one page app layout
<body>
<template is="dom-bind" id="app">
<paper-drawer-panel>
<paper-scroll-header-panel drawer fixed>
<paper-toolbar> ... </paper-toolbar>
<paper-menu> ... </paper-menu>
</paper-scroll-header-panel>
<paper-scroll-header-panel main condenses keep-condensed-header>
<paper-toolbar> ... </paper-toolbar>
<iron-pages attr-for-selected="data-route" selected="{{route}}">
<section data-route="foo"> ... </section>
<section data-route="contact">
<!-- HERE IS MY DOM-MODULE -->
<lista-contatti></lista-contatti>
</section>
</iron-pages>
</paper-scroll-header-panel>
</paper-drawer-panel>
</template>
</body>
My iron-list does not work as expected with paper-scroll-header-panel because it is nested inside many elements like iron-pages, section and my custom dom-module. The list can't interact with the header height and doesn't scroll seamlessly with it.

In earlier versions of polymer you had to bind your list's scrollTarget to header panel's scroller. There is a slide about this in a Polymer 0.5 video #11:58. In which case the updated code in Polymer 1.0 might look something like:
<paper-scroll-header-panel id="hPanel" main condenses keep-condensed-header>
<iron-list id="list" items="{{data}}" as="item" >
...
</iron-list>
</paper-scroll-header-panel>
script:
document.querySelector("#list").scrollTarget = document.querySelector("#hPanel").scroller;
NB: I haven't tested this yet but figured it might help to point you in the right direction for now.

Related

How to use app-route in polymer 2 to have deep paths?

This is part of polymer application starter kit code. I just added a my-news-list.html to elements in src:
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<app-drawer-layout fullbleed>
<!-- Drawer content -->
<app-drawer id="drawer" slot="drawer">
<app-toolbar>Menu</app-toolbar>
<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
<a name="news" href="/news">News</a>
<a name="view1" href="/view1">View One</a>
</iron-selector>
</app-drawer>
<!-- Main content -->
<app-header-layout has-scrolling-region>
<app-header slot="header" condenses reveals effects="waterfall">
<app-toolbar>
<paper-icon-button icon="my-icons:menu" drawer-toggle></paper-icon-button>
<div main-title>My App</div>
</app-toolbar>
</app-header>
<iron-pages
selected="[[page]]"
attr-for-selected="name"
fallback-selection="view404"
role="main">
<my-news-list name="news" route="{{subroute}}"></my-news-list>
<my-view1 name="view1"></my-view1>
<my-view404 name="view404"></my-view404>
</iron-pages>
</app-header-layout>
</app-drawer-layout>
Everything is OK, <my-news-list> and <my-view1> loads correctly when click on theme in <iron-selector>. in <my-news-list> element I got list of all news with <iron-ajax> and it works fine:
<iron-ajax auto url="localhost/api/news/news" handle-as="json" last-response="{{newsList}}"></iron-ajax>
<template is="dom-repeat" items="{{newsList}}">
[[item.title]]
</template>
I have a other element for viewing single news content, named <my-news-view> that I want to load it when click on title of each news in <my-news-list>. On click path changes to: localhost:8081:/news/2 correctly but <my-news-list> element loads again Instead of <my-news-view>.
I don't paste other elements codes(bindings, ...).
Now I want to know how config <app-route> and use subroute to have load elements in this paths:
// For News
/news //all news list. loads my-news-list element
/news/12 //news[12] view. loads my-news-view elemnt
/news/categories //all categories list view. loads my-news-categories element
/news/categories/3 //category[3] news list view. loads my-news-category element
// and jobs similar to module
/Jobs
/jobs/country/cityName
/jobs/country/cityName/featured
Thanks for your help.
You should declare you "my-news-view" component in "iron-pages" just like you do:
<iron-pages selected="[[page]]" attr-for-selected="name"
fallback-selection="view404" role="main">
<my-news-view name="news-view" route="{{subroute}}" />
</iron-pages>
So iron-pages would know what component to show when user navigate to /news-view/12 based on name attribute not component name itself.
BUT. There are some tricky parts on your solution:
Note how you pass subroute to child components to decouple it internal
routing mechanism from actual url path where it resides.
Starter kit uses lazy-loading to import components and inside that function it adds prefix 'my-' to actual route 'news-view'. So that is how result component name to load become 'my-news-view'. That may confuse.
You could read more about this polymer shop case study.
PS: personally I think that the way the polymers sample app routing works confused a lot because it looks like web-server static name resolution (based on component name, and not components attribute 'name') but it don't.
You should add the component inside the component and then use the sub route to know the id for
Try dna-router. It is now compatible with Polymer 2.0 project.
Please follow this answer - https://stackoverflow.com/a/31236817/5069120
Or visit https://github.com/Saquib764/dna-router

Manually Querying Elements In Nested Shadow Dom? API has no recursion? Wasn't like this in PSK1

This is in the context of Chrome where Shadow dom is baked in...
In Polymer Starter Kit 1, there is a great example of being able to globally query a element - app.$.paperDrawerPanel.closeDrawer();. Here is another great example - var middleContainer = Polymer.dom(document).querySelector('#mainToolbar .middle-container');
I assumed it traversed shadow doms recursively. I'm assuming that the polymer elements, such as paperDrawerPanel, were in a shadow dom at some point even though I didn't have to use Polymer.dom().
But in the starter kit template for Polymer Starter kit 2, I am having to manually query each nested shadow dom.
For example I have:
my-app.html
<dom-module id="my-app">
<template>
<app-header-layout fullbleed has-scrolling-region>
<!-- Drawer content -->
<app-header fixed shadow>
<app-toolbar>
<paper-icon-button icon="menu" on-tap="_drawerToggle"></paper-icon-button>
<div main-title class="app-name">Dolphin</div>
</app-toolbar>
</app-header>
<!-- Main content -->
<iron-pages
selected="[[page]]"
attr-for-selected="name"
fallback-selection="view404"
role="main">
<my-view1 name="view1"></my-view1>
and
my-view.html:
<dom-module id="my-view1">
<template>
<app-drawer id="drawer">
<div class='left-bar-container'>
<app-toolbar class="toolbar-drawer">Menu</app-toolbar>
<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
<a name="view1" href="/view1">Home</a>
<a name="view2" href="/view2">Users</a>
<a name="view3" href="/view3">Contact</a>
</iron-selector>
</div>
</app-drawer>
If I want to query <app-drawer id="drawer"> globally I have to do this crazy routine:
level1 = Polymer.dom(document.querySelector('my-app').root)
level2 = Polymer.dom(level1).querySelector('my-view1').root
Polymer.dom(level2).querySelector('#drawer')
What changed between PSK1 and PSK2 in Polymer where I have to manually query the nested Shadow Doms? It seems the query API used to have recursion. And is there a better to do this if I need to query #drawer globally?
After asking on the Polymer channel, Shady dom pierces the dom tree where the elements reside in the light dom. PSk1 uses shady dom. PSK2 defaults to Shadow dom if available. With that, I have to manually query each nested level.

Polymer two drawer inside component

I am using the example code for two drawers found here.
<app-drawer-layout>
<app-drawer swipe-open></app-drawer>
<app-drawer id="endDrawer" align="end" swipe-open></app-drawer>
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div main-title></div>
<paper-icon-button icon="info" onclick="document.getElementById('endDrawer').toggle();"></paper-icon-button>
</app-toolbar>
<sample-content size="100"></sample-content>
</app-drawer-layout>
This works if I put the code on in index.html but If I put it inside a component, and then reference the component in index.html, I get the following error:
Uncaught TypeError: Cannot read property 'toggle' of null
Can anyone please shed some light on this?
Note: This error happens in Chrome but not Safari. Haven't tested anything else.
This happens because inside a component code the document.getElementById will not work as expected. Do you have Shadow DOM enabled by any chance?
You should use Polymer's event binding syntax and get the element using the node finding feature.
<dom-module id="my-app">
</template>
<paper-icon-button icon="info" on-tap="toggleEndDrawer"></paper-icon-button>
</template>
</dom-module>
<script>
Polymer({
is: 'my-app',
toggleEndDrawer: function() {
this.$.endDrawer.toggle();
}
</script>

Polymer - Nesting a content tag inside a conditional template

I'm using a conditional template to distribute content that is passed into the element. If the condition is true, it will show the first content element, otherwise the second. I noticed that when I update the condition the already distributed content is not updated. Once it is visible it will remain visible.
My first attempt looked like this:
<template is="dom-if" if="{{test}}">
<content select=".first">
</content>
</template>
<template is="dom-if" if="{{!test}}">
<content select=".second">
</content>
</template>
I noticed that it will work, if the content is wrapped in another element.
<template is="dom-if" if="{{test}}">
<div>
<content select=".first">
</content>
</div>
</template>
<template is="dom-if" if="{{!test}}">
<div>
<content select=".second">
</content>
</div>
</template>
I've created a plunker that demonstrates both cases.
Is there an explanation for this behaviour? Is it on purpose or a bug?
This is actually per design. Here`s what the Polymer team had to say on the issue on Github.
Hiding a <content> has no effect on the visibility of its distributed children (per spec), so your options are to wrap the content with a wrapper element that can be hidden (and will hide the distributed children), or use restamp which will pull the <content> out of the DOM all together.
It is slightly unintuitive that the restamp and non-restamp setups work differently, however it is a result of the non-restamp behavior which hides rather than destroying DOM as a performance optimization.

What is the best practice for Polymer core-menu

I started using the polymer core-pages and core-menu elements.
And I wan to know if I am implementing it right.
My page is simple and looks like this:
<core-menu selected="0" selected="{{selected}}">
<core-item label="Organization"></core-item>
<core-item label="Bank Setup"></core-item>
</core-header-panel>
<span tool class="tabAdminPolymer_title"></span>
<core-pages class="sss" selected="{{selected}}">
<div class="pages">
Hi there content1!
</div>
</core-pages>
Using Java Script on menu click event I am changing the content of the class .page
My content is backbone controls that renders using obj.render js function.
Your implementation is sound but there are some simple errors which are breaking it. Please try the following corrections.
You're using the "selected" attribute twice:
<core-menu selected="0" selected="{{selected}}">
to
<core-menu selected="{{selected}}">
You're closing the wrong tag:
</core-header-panel>
to
</core-menu>
That's it. Code works otherwise.