Reputation: 316
I am trying to use an iron-list
(and iron-scroll-threshold
) within a app-header-layout
with has-scrolling-region
.
I generated the basic app layout with the polymer-CLI.
If I do not use has-scrolling-region
on the app-header-layout
and use "document"
for scroll-target
on the iron-list
it kinda works. But with this solution the scrollbar belongs to the window and does not slide beneath the header and I obviously cannot get the nice "waterfall" behaviour that is usually associated with these kinds of layouts.
Therefore, I use has-scrolling-region
on the app-header-layout
, but what is the right way to pass the corresponding scoller to the scroll-target
property of the iron-list
?
<!-- Main content -->
<app-header-layout has-scrolling-region id="layout">
<app-header condenses reveals effects="waterfall">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div title>Twiamo</div>
</app-toolbar>
</app-header>
<iron-pages role="main" selected="[[page]]" attr-for-selected="name" id="page">
<my-iron-list name="view1" scroll-target="[[_getScrollTarget()]]"></my-iron-list>
<my-view2 name="view2"></my-view2>
<my-view3 name="view3"></my-view3>
</iron-pages>
</app-header-layout>
I looked into the implementation of app-header-layout
to find the right element. This expression actually yields me the right element and everything works fine.
_getScrollTarget: function() {
return this.$.layout.shadowRoot.querySelector("#contentContainer");
}
But there has to be a better, a right way? Grabbing into the shadow DOM of the app-header-layout
is not exactly using "public interface"!
To complete the example, here my code for my-iron-list
. My-iron-list
wraps and iron-list, iron-scroll-theshold
, and some dummy data provider stuff. The scroll-target
on my-iron-list
is just passed to the iron-list
and iron-scroll-threshold
within my-iron-list
:
<dom-module id="my-iron-list">
<template>
<iron-list items="[]" as=item id="list" scroll-target="[[scrollTarget]]">
<template>
<div class="item">[[item]]</div>
</template>
</iron-list>
<iron-scroll-threshold
id="scrollTheshold"
lower-threshold="100"
on-lower-threshold="_loadMoreData"
scroll-target="[[scrollTarget]]">
</iron-scroll-threshold>
</template>
<script>
Polymer({
is: 'my-iron-list',
properties: {
page: {
type : Number,
value : 0
},
perPage: {
type : Number,
value : 100
},
scrollTarget: HTMLElement,
},
_pushPage: function() {
for (i = 0; i < this.perPage; i++) {
this.$.list.push('items', 'Entry number ' + (i+1+this.page*this.perPage));
}
},
_loadMoreData: function() {
this._pushPage();
this.page = this.page + 1;
this.$.scrollTheshold.clearTriggers();
}
});
</script>
</dom-module>
Upvotes: 5
Views: 3111
Reputation: 433
If anyone is coming here for an answer in 2017, I'm just letting you know that the same issue persists in Polymer 2.0.
I was able to overcome the issue by having the following code in my app shell (eg. PSK's my-app.html):
First, put an id attribute of 'layout' on your app-header-layout element.
Next, add this to your Polymer class (in your my-app.html equivalent):
static get properties() {
return {
scrollTarget: HTMLElement,
}
}
ready() {
super.ready();
this.scrollTarget = this.$.layout.shadowRoot.querySelector("#contentContainer");
}
Then, pass in the property to a scroll-target attribute on your lazy-loaded pages:
<my-page scroll-target="[[scrollTarget]]"></my-page>
Finally, in your lazy-loaded pages (eg. my-page):
<iron-list scroll-target="[[scrollTarget]]"></iron-list>
...
static get properties() {
return {
scrollTarget: HTMLElement,
}
}
This isn't an ideal solution, but it works.
Upvotes: 4
Reputation: 126
I struggled with the same issue. While I was using iron-scroll-target-behavior
instead of iron-scroll-threshold
, I still needed to pass a scroll-target reference to an element inside a app-layout-header
.
If has-scrolling-region
is true, app-header-layout
sets the scroll-target to be an internal div with an ID of #contentContainer
. You can target this div and pass it as the scroll-target to your iron-list.
You would just need to alter the _getScrollTarget
function inside your original code.
_getScrollTarget: function() {
return this.$.layout.$.contentContainer;
}
Hope it helps!
Upvotes: 4
Reputation: 41
I have the same problem as you, for now the cleanest anwser I have was to use the app-header scrollTarget.
In your case move add an id to the app-header
<app-header condenses reveals effects="waterfall" id="header">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div title>Twiamo</div>
</app-toolbar>
</app-header>
and then instead of
_getScrollTarget: function() {
return this.$.layout.shadowRoot.querySelector("#contentContainer");
}
just use the scrollTarget property
_getScrollTarget: function() {
return this.$.header.scrollTarget;
}
If you found out a better way let me know.
Cheers,
Upvotes: 4