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>
Related
I have included api, before everything were working perfect in polymer 1.7, after upgraded to polymer ^2.0 google map does not renders.
here is my code in main app page written polymer class base:
<iron-pages role="main" selected="[[page]]" attr-for-selected="name" selected-attribute="visible" fallback-selection="404">
<jj-maps name="maps" user="{{user}}" sprof="{{sprof}}"></jj-maps>
<jj-list name="list" > Jobs </jj-list>
<jj-infos name="infos"> infos </jj-infos>
<jj-contacts name="contacts" > Contacts </jj-contacts>
<jj-messages name="messages"> Messages </jj-messages>
<jj-404 name="404" > 404 </jj-404>
</iron-pages>
at jj-maps.html code sample is :
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="import" href="../bower_components/google-map/google-map-marker.html">
style codes in template tag:
<dom-module id="jj-maps">
<template>
<style include="iron-flex iron-flex-alignment">
:host {
.....
google-map, #mapResults {
margin-top: 10px;
position: relative;
height: 100vh;
width: 100vh%;
z-index: 1;
}
....
<div id="mapResults">
<google-map
id="map"
map="{{map}}"
latitude="[[latitude]]"
longitude="[[longitude]]"
zoom="10"
api-key="[[myApiKey]]"
on-google-map-ready= '_mapLoaded'
additional-map-options='{"gestureHandling" : "greedy"}'
>
<google-map-marker map="{{map}}" slot="marker" latitude="{{latitude}}" longitude="{{longitude}}"
title="You are here !" icon="./src/image/gpslocc.png" draggable="true">
</google-map-marker>
<template is="dom-repeat" items="{{sprof}}" as="item">
<google-map-marker map="[[map]]" slot="marker" latitude="[[item.myLat]]" longitude="[[item.myLng]]" animation="DROP" click-events title="{{item.prof}}" icon="{{calculateIconType(item.isFree)}}" on-google-map-marker-click='showUserDetail' userid="[[item.uid]]" isFree="{{item.isFree}}" >
</google-map-marker>
</template>
<paper-fab icon="maps:my-location" on-tap="updateCurrentPosition"></paper-fab>
</google-map>
</div>
</template>
this code works perfect in previous polymer. And Another point when I bower install the dependencies as bower install --save GoogleWebComponents/google-map
bower asks me for two as :
- Unable to find a suitable version for polymer, please choose one by typing one of the numbers below:
I chose : 7) polymer#^2.0.0 which resolved to 2.0.1 and is required by myApp
- Unable to find a suitable version for webcomponentsjs, please choose one by typing one of the numbers below:
I chose : 2) webcomponentsjs#^1.0.0 which resolved to 1.0.1 and is required by myApp
Sorry in advance that I ve written detailed codes. Meanwhile I have tried many options but could not able to render map in my jj-maps elements (class base template, even I have tried legacy template (as same as polymer 1.7 ver)
Here is is console warning :
dom-module.html:24 dom-module google-map has style outside template
dom-module google-map-marker has style outside template
Maps are not rendering...
So, how to solve ? Thanks in advance. (previous polymer ver. working at jobijoy.com
I'm having exactly same issue. Tried to add slot="marker" to google-map-marker as someone suggested Polymer 2.0 issue in github but doesn't work for me. It looks like the google-map component's size is set to 0 by 0 thus does not display at all. Since the google components are not updated to be compatible with Polymer 2.0. I've manually updated my local google-map.html and google-map-marker.html files under bower_component folder and moved the style tags into the template tags. The warnings are gone and the map displays now. I guess we have to wait for the update of the google components for things to work properly. I hope this helps.
slot="marker"
should solve the issue.
Unfortunately the example in the code does not insert this important line.
Here is the without slot="markers" current code example:
<google-map latitude="37.77493" longitude="-122.41942" fit-to-markers>
<google-map-marker latitude="37.779" longitude="-122.3892" draggable="true" title="Go Giants!">
</google-map-marker>
<google-map-marker latitude="37.777" longitude="-122.38911">
</google-map-marker>
</google-map>
And below the suggested corrected example that should be inside the code:
<google-map latitude="37.77493" longitude="-122.41942" fit-to-markers>
<google-map-marker slot="markers" latitude="37.779" longitude="-122.3892" draggable="true" title="Go Giants!">
</google-map-marker>
<google-map-marker slot="markers" latitude="37.777" longitude="-122.38911">
</google-map-marker>
</google-map>
What is happening?
google-map does not know when markers are inserted or updated because without the attribute slot="markers" they are inserted outside the slot where they should be inserted in.
Several consequences can happen from this issue: the map can be viewed, but not respond to important events, like fit-to-markers.
In these turbulent moves from original without-slots version to the current slotted version (and soon moving to polymer 3.0 version) of the excellent google-map webcomponent, there is a high chance that the busy developers simply forgot to add this important slot="markers" attribute in the example that shows how to add each new google-map-marker webcomponent inside google-map.
This only complements the already correct above answer. If anyone needed more explanation, I offer these, If I am correct, of course (please correct me if I made wrong conclusions).
You can detect this flaw inspecting your google-map element. Without the slot="markers" correction, open google-map; inside it, open iron-selector; and finally inside it open the element <slot id="markers" name="markers"><slot>. If you do not use the suggested correction, this slot will be empty. If you use this suggested correction, this slot will contain references to each google-map-marker. And so the google-map element will be able to handle several events that rely on detecting when each marker is inserted or updated.
Sorry for the long answer.
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
In a simple routing configuration in Polymer, like that obtained from the starter-kit:
<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>
<app-toolbar>Menu</app-toolbar>
<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
<a name="view1" href="/view1">View One</a>
<a name="view2" href="/view2">View Two</a>
<a name="view3" href="/view3">View Three</a>
</iron-selector>
</app-drawer>
<!-- Main content -->
<app-header-layout has-scrolling-region>
<app-header condenses reveals effects="waterfall">
<app-toolbar>
<paper-icon-button icon="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-view1 name="view1"></my-view1>
<my-view2 name="view2"></my-view2>
<my-view3 name="view3"></my-view3>
<my-view404 name="view404"></my-view404>
</iron-pages>
</app-header-layout>
</app-drawer-layout>
and a view with a button which if pressed should change the route, like this:
<dom-module id="my-view1">
<template>
<paper-button raised on-tap="changeRoute">Change route</paper-button>
</template>
<script>
Polymer({
is: 'my-view1',
changeRoute() {
// How to change route here?
}
});
</script>
</dom-module>
how can I change the route programmatically, in the event handler above? I tried changing window.location without success (I'm inside Electron, not sure if it's part of the problem).
From the Polymer docs, about changing routes:
Updating the route. The route object is read-write, so you can use
two-way data binding or this.set to update the route. Both the route
and routeData objects can be manipulated this way. For example:
this.set('route.path', '/search/');
Or:
this.set('routeData.user', 'mary');
but this is correct (and works) if done inside the main component (the one that defines the routes), while it doesn't work if called inside a view. Another way to put this question maybe is: how can I access the main router object from an inner component?
There's a few ways to do this, I may have gone overboard but I started to get into it so here goes...
Based on the answer you gave it looks like you just want to "go back". If that's the case you could just use
history.back();
Or if you want to move to a new path then a more robust, including more SEO friendly approach (I believe) is to use something like:
<a href="/newpath" tabindex="-1">
<paper-button>Change Route</paper-button>
</a>
Or the answer by #Carlos works too, but the app-route "philosophy" seems to be more about allowing a decentralized routing approach & so passing an event up to let another component handle the route feels kind of like it's going against the grain. Although this is not necessarily the case since a component can be quite simple, maybe just a button, icon, etc, so you would probably want routing handled by a parent element. In this case though it looks like your component is a full view so I'd lean more towards it being a case where it might handle the routing itself.
I'd also say something similar to the above for #tony19's answer as well.
I think the biggest drawback of the approach in your own answer is that you're digging in the guts of another element so you've tightly coupled to it. That one is definitely not recommended.
Oh & one more way to change the route:
window.history.pushState({}, null, '/new_path');
window.dispatchEvent(new CustomEvent('location-changed'));
This is given here - https://github.com/PolymerElements/app-route#integrating-with-other-routing-code But this is really more for working with other routing code or special situations & would be pretty hacky in your case.
Uhm. Turned out it was not so difficult:
document.querySelector("main-window").set('route.path', "/");
where main-window is the container component that defines the routes (first source file).
Does anyone have a better/more general approach to this problem?
I had the same issue and solved it like by adding the routing-elements to the views as well:
<app-location route="{{route}}"></app-location>
<app-route route="{{route}}" pattern="/app/:view" data="{{routeData}}" tail="{{subRoute}}"></app-route>
<app-route route="{{subRoute}}" pattern="/:id" data="{{idData}}" active="{{onDetailPage}}"></app-route>
then you can change the route from within the element like this:
this.set("route.path", "/app/foo");
Your 'view1' could fire a custom event that would trigger a route change in your app.
This would follow the observer pattern recommended in: Thinking in Polymer (The Polymer Summit 2015)
Note: the answer to this question may also help you.
You can easily do so with the path property of the app-location's element:
changeRoute() {
var $router = this.shadowRoot.querySelector("app-location");
$router.path = "/view1";
}
Here the element's documentation app-location:
Setting the path property will fire up the path-changed event... This will begin the events' cascade to the iron-pages element and switch the view.
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.
I'm trying to include a paper-dropdown-menu element within a custom Polymer element and I am seeing the following errors:
Uncaught NotSupportedError: Failed to execute 'animate' on 'Element': Partial keyframes are not supported.
animation-constructor.js:61 Uncaught NotSupportedError: Failed to execute 'animate' on 'Element': Partial keyframes are not supported.
animation-constructor.js:61 Uncaught NotSupportedError: Failed to execute 'animate' on 'Element': Partial keyframes are not supported.
and also this warning:
core-dropdown-overlay: dropdown's offsetParent must be the relatedTarget or the relatedTarget's offsetParent!
The paper-dropdown-menus display fine and these errors/warnings occur when they are clicked. The code works fine when embedded in the page itself.
My page is structured like so:
<page-form>
...
<subform-element></subform-element>
...
</page-form>
Page form is another polymer element that represents my page, and subform-element is a piece of the form which holds the paper-dropdown-menu.
<polymer-element name="subform-element" noscript>
<template>
<link rel="stylesheet" href="subform-element.css">
<div layout horizontal center>
<paper-dropdown-menu label="Disease" layered flex>
<paper-dropdown class="dropdown core-transition core-closed">
<core-menu class="menu">
<paper-item tabindex="0">Foulbrood</paper-item>
<paper-item tabindex="0">Varroa</paper-item>
<paper-item tabindex="0">Tracheal Mites</paper-item>
<paper-item tabindex="0">Other</paper-item>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
<paper-input-decorator label="disease notes" floatinglabel="disease notes" flex>
<input is="core-input" placeholder="disease notes">
</paper-input-decorator>
</div>
</template>
</polymer-element>
I'm seeing the errors in Polymer version 0.5.5 and Chrome 41.