I've installed a new Polymer Starter Kit, and have the code below.
<app-drawer-layout fullbleed>
<!-- Drawer content -->
<app-drawer>
<app-toolbar>
How can I make the app-drawer element be closed when the layout loads?
If i trigger .close() on the element when should I run this?
It won't work for ready or attatched life cycle callbacks
But that would mean the menu opens and closes which i would like to avoid, what i really want to happen is when the page loads the menu is closed,
when I get a callback from the server to say the user is authenticated then call
this.$.menu.open() // where i've given app-drawer the if of menu
If what you want is to not display the drawer no matter the viewport width unless the user interacts, all you need to do is to set the app-drawer-layout's forceNarrow property to true like this:
<app-drawer-layout fullbleed force-narrow>
<!-- Content -->
</app-drawer-layout>
I'm assuming this is a follow up to: Polymer 1.0 App-Drawer - Uncaught TypeError when not rendered via dom-if
Given:
<app-drawer-layout id="layout" fullbleed>
<app-drawer id="drawer">
...
</app-drawer>
</<app-drawer-layout>
You could set the <app-drawer>.hidden property and then <app-drawer-layout>.resetLayout() based on the new value of signedIn, using an observer:
Polymer({
...
properties : {
signedIn: {
type: Boolean,
value: false,
observer: '_signedInChanged'
}
},
_signedInChanged: function(signedIn) {
this.$.drawer.hidden = !signedIn;
this.$.layout.resetLayout();
}
);
codepen
Related
I intend to implement an infinite scroller using with PSK v3 by setting the scroll-target to "document", but it just doesn't work for PSK. Below is the code snippet:
<iron-scroll-threshold id="threshold"
scroll-target="document"
on-lower-threshold="queryMoreData">
<iron-list items="[[items]]" grid>
<template>
<div>
<div class="content">
item: [[item.n]]
</div>
</div>
</template>
</iron-list>
</iron-scroll-threshold>
I have tested scroll-target="document" with plain HTML, and it's working nicely. I want to know how should it be set for PSK to trigger an event when user scroll to the end of a particular page/view.
Apparently, you need to set the scroll-target of <iron-scroll-threshold> to the scroll-target of <app-header> with the following code in ready():-
ready() {
{ // Set scroll target for <iron-scroll-threshold>
let myApp = document.querySelector('my-app');
let appHeader = myApp.shadowRoot.querySelector('app-header');
this.$.threshold.scrollTarget = appHeader.scrollTarget;
}
}
Sometimes, your scroll position is at enough lower place at start than queryMoreData functions fire ones. In this function, you will need to clear the threshold by calling the clearTriggers method into queryMoreData function :
queryMoreData() {
//check if you have more data to load than
ironScrollTheshold.clearTriggers();
}
After which it will begin listening again for the scroll position to reach the threshold again assuming the content in the scrollable region has grown.
You have to set the scroll-target attribute of the iron-scroll-threshold element to 'document'.
Also note the scroll-target attribute of the iron-list is set to the id of the iron-scroll-threshold element - 'threshold'.
<iron-scroll-threshold scroll-target="document" id="threshold" on-lower-threshold="loadMoreData" lower-threshold="100">
<iron-list id="list" items="[[items]]" as="item" scroll-target="threshold" grid>
<!-- template -->
</iron-list>
</iron-scroll-threshold>
The transform navigation demo described in responsive-navigation-pattern section of the Polymer documentation uses an array of items to build up a single menu that is used twice (in the app-drawer and in the app-header). See the source here.
A simplified example is shown below:
<app-drawer-layout>
<app-drawer>
<paper-menu>
<!-- MENU ITEMS -->
</paper-menu>
</app-drawer>
<app-header-layout>
<app-header>
<app-toolbar>
<div main-title>App name</div>
<paper-tabs>
<!-- SAME MENU ITEMS HERE -->
</paper-tabs>
</app-toolbar>
</app-header>
main content
</app-header-layout>
</app-drawer-layout>
This is part of the script that initializes the menu items:
items: {
type: Array,
value: function() {
return ['Item One', 'Item Two', 'Item Three', 'Item Four', 'Item Five'];
}
}
What would be a better way to initialize the menu only once without using an array?
Defining the menu as a new element would be great but this will not work I guess because in the drawer these are paper-menu items and in the header these are paper-tabs.
Create a new element that will display an array of items.
Bind the data from items to your element attribute display-items.
You also should have an attribute to propagate the selected item.
<item-menu display-items=[[items]] selected-item={{selectedItem}}></item-menu>
<app-drawer-layout>
<app-drawer>
<paper-menu>
<item-menu display-items=[[items]] selected-item={{selectedItem}}></item-menu>
</paper-menu>
</app-drawer>
<app-header-layout>
<app-header>
<app-toolbar>
<div main-title>App name</div>
<paper-tabs>
<item-menu display-items=[[items]] selected-item={{selectedItem}}></item-menu>
</paper-tabs>
</app-toolbar>
</app-header>
main content
</app-header-layout>
</app-drawer-layout>
Ps: This code only demonstrates how to propagate the value of the array items to multiple polymer elements. I assumed that you were familiar with creating new polymer element and importing them into your app.
I have a project with Polymer + Reveal.js
I have a view with polymer that gets all the Slides/Sections.
<template is="dom-repeat" items="[[my.slides]]" as="slide">
<section>
<h1>slide.title</h1>
<h2>slide.content</h2>
</section>
</template>
When I try to start Reveal.js, I have the issue related to:
(index):21136 Uncaught TypeError: Cannot read property
'querySelectorAll' of undefined
I think is because Reveal.js cannot select a Webcomponent generated by Polymer, because Reveal.js needs to have all slides content wrote on the html file by separate.
Then my question is: How to use Polymer Webcomponents with Reveal,js?
Alan: Yes, you are right.
Now I am creating DOM elements directly with JS avoiding Polymer shadowDOM elements.
Then I created a function called createSlides where - based in a JSON response - I appending slides (sections) within slides div.
Fist I create a Polymer template similar to:
<template>
<div class="reveal">
<div id="slides" class="slides">
<section>
This section will be removed
</section>
</div>
</div>
</template>
Next I removed the unused slide and appended some slides. Finally start the Reveal presentation
ready()
{
this.removeInitialSlide();
this.addSomeSlides();
this.startRevealPresentation();
}
clearInitialSlides()
{
var slidesComp = this.$.slides;
while (slidesComp.hasChildNodes()) {
slidesComp.removeChild(slidesComp.lastChild);
}
}
addSomeSlides()
{
var slide1 = document.createElement("section");
var image = document.createElement("img");
image.src = "some/path/to/image.jpg";
slide1.appendChild(image);
this.$.slides.appendChild(slide1);
var slide2 = document.createElement("section");
slide2.innerHTML = "<h1>Test content</h1>"
this.$.slides.appendChild(slide2);
}
Working fine for now.
I think you most likely can't use reveal.js in a web component created with Polymer right now and here's why.
If you look at reveal.js's code it looks for dom elements with the reveal and slides classes on the main document like this:
dom.wrapper = document.querySelector( '.reveal' );
dom.slides = document.querySelector( '.reveal .slides' );
The problem with that is that Polymer elements have their own local dom which is a different dom tree which can't be accessed using methods like document.querySelector which means reveal.js can't access to them.
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>
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,
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!
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.
I have a paper-drawer-panel that has a closed drawer. When I click a fab I open the drawer and hide the fab. However when the drawer closes again I would like to re-show the fab.
My question is this: How do I know when the drawer is closing?
I looked into the two events listed in the paper-drawer-panel docs and tried both paper-select and paper-responsive-change. I used them in the following way:
html:
<paper-drawer-panel right-drawer force-narrow narrow paper-select="changed">
<div main> content... </div>
<div drawer> drawer content </div>
</paper-drawer-panel>
js:
changed:function(){
console.log("inside event");
}
should this work? can anyone offer some suggestions?
As I mentioned in the comment, I solved this by using TrevorDixon's advice and changing paper-select to on-iron-select
http://jsbin.com/winedi/edit?html,output
menuToggle: function() {
if (this.$.paper_drawer_panel.narrow && $(this.$.paper_drawer_panel).width() < parseInt(this.$.paper_drawer_panel.responsiveWidth)) {
this.$.paper_drawer_panel.togglePanel();
} else {
this.$.paper_drawer_panel.forceNarrow = !this.$.paper_drawer_panel.forceNarrow;
}
}
took from Polymer 1.0 paper-drawer-panel toggle is not working