Polymer _routePageChagned running twice - polymer

When I change the page via a link or via JS this.set('route.path', 'packages'); the _routePageChagned method is running twice. Its also happening on when the page loads for the first time.
This is also happening in the default polymer starter kit template build from the CLI.
I'm I missing something? How can this occur?
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="my-icons.html">
<link rel="import" href="pages/my-loading.html">
<dom-module id="my-app">
<template>
<style>
</style>
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}"></app-route>
<iron-pages
id="pages"
selected="[[page]]"
attr-for-selected="name"
fallback-selection="view404"
selected-attribute="visible"
role="main">
<my-loading name="loading"></my-loading>
<my-login name="login"></my-login>
<my-view404 name="view404"></my-view404>
<my-view403 name="view403"></my-view403>
<my-packages name="packages"></my-packages>
</iron-pages>
</template>
<script>
Polymer({
is: 'my-app',
properties: {
/**
* The current page.
*/
page: {
type: String,
reflectToAttribute: true
},
},
observers: [
'_routePageChanged(routeData.page)'
],
_routePageChanged: function(page) {
console.log(page);
var resolvedPageUrl = this.resolveUrl('pages/my-' + page + '.html');
this.importHref(resolvedPageUrl, function() {
this.page = page;
}.bind(this), undefined, false);
}
});
</script>
</dom-module>

This works as a hack fix, still no idea why it's needed though.
_pageChange: function(page) {
this.debounce(function() {
// Load page import on demand. Show 404 page if fails
var resolvedPageUrl = this.resolveUrl('pages/my-' + page + '.html');
this.importHref(resolvedPageUrl,
this._pageLoaded.bind(this, page), // loaded callback
this._pageChange.bind(this, 'view404'),
true);
}.bind(this), 100);
}

Related

Polymer dom-if not re-firing

I have been having problems with my Polymer 2 app, I first through it was the routing but I found that after hitting this page and the Dom-if fires when navigating back to the page it is not re-firing.
EG,
If I am on url/matters/6719 it displays the details page, but if I click the back button and go to url/matters the dom-if is not being hit again and its still showing me the details page,
It also happens when using my navigation selector which is set up like the PWA starter kit.
<link rel="import" href="../bower_components/polymer/polymer-element.html">
<link rel="import" href="../bower_components/app-route/app-location.html">
<link rel="import" href="../bower_components/app-route/app-route.html">
<link rel="import" href="../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../bower_components/iron-selector/iron-selector.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="Matters/matter-list.html">
<link rel="import" href="MatParties/matparty-list.html">
<link rel="lazy-import" href="Matters/matter-detail.html">
<dom-module id="my-matters">
<template>
<style include="shared-styles">
:host {
display: block;
padding: 10px;
}
</style>
<app-route route="{{route}}" pattern="/:matter_id" data="{{routeData}}" tail="{{subroute}}">
<app-route route="{{subroute}}" pattern="/matparties/:this_page" data="{{pageData}}"></app-route>
</app-route>
<div class="card">
<template is="dom-if" if="[[_subidIsDefined(pageData.this_page)]]">
<matparty-list linkedmatpartyid="[[pageData.this_page]]"></matparty-list>
</template>
<template is="dom-if" if="[[!_subidIsDefined(pageData.this_page)]]">
<template is="dom-if" if="[[!_idIsDefined(routeData.matter_id)]]">
<matter-list></matter-list>
</template>
<template is="dom-if" if="[[_idIsDefined(routeData.matter_id)]]">
<matter-detail linkedmatterid="[[routeData.matter_id]]"></matter-detail>
</template>
</template>
</template>
<script>
class Matters extends Polymer.Element {
static get is() { return 'my-matters'; }
_subidIsDefined(subid) {
//There are probably ways to optimize this
if (subid) {
return true;
}
return false;
}
_idIsDefined(id) {
//There are probably ways to optimize this
if (id) {
return true;
}
return false;
}
}
window.customElements.define(Matters.is, Matters);
</script>
</dom-module>
have you checked the pattern? Normally the pattern should respect the url pattern.... in your case "url/matters/6719"
Since you have defined the pattern="/matparties/:this_page" on the router and matparties is != 'matters' in 'url/matters/6719' that could generate the error. I don't know if you have defined a base url that generate also some issues on this regards.
So the url should be matparties/6719 to match the pattern and resolve into the dom-if

"Map container not found" error with Polymer+PubNub

I am currently experimenting with PubNub's EON Map library. It is a real-time mapping library that makes use of MapBox and PubNub's live data stream infrastructure.
I'm trying to build a simple PWA that publishes a string every time the location changes.
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="shared-styles.html">
<link rel="import" href="../bower_components/geo-location/geo-location.html">
<link rel="import" href="../bower_components/google-map/google-map.html">
<link rel="stylesheet" type="text/css" href="../bower_components/mapbox.js/mapbox.css">
<script src="../bower_components/mapbox.js/mapbox.js"></script>
<script src="../bower_components/pubnub/dist/web/pubnub.min.js"></script>
<script src="../bower_components/eon-map/pubnub-mapbox.js"></script>
<!-- Instantiate PubNub -->
<script type="text/javascript">
console.log('Init PubNub');
var channel = 'pubnub-mapbox';
var pub = new PubNub({
publishKey: 'myPubKey',
subscribeKey: 'mySubKey',
logVerbosity: true
});
</script>
<dom-module id="my-view1">
<template>
<div id='map'></div>
<script type="text/javascript">
var map = eon.map({
pubnub: pub,
id: 'map',
mbToken: 'myToken',
mbId: 'myId',
channels: [channel]
});
</script>
</template>
<script>
Polymer({
is: 'my-view1',
});
The problem arises when the browser tries to instantiate the EON map. Even though there is a div element, I get this error message:
Uncaught Error: Map container not found.
at e._initContainer (leaflet-src.js:1979)
at e.initialize (leaflet-src.js:1532)
at e.initialize (map.js:37)
at new e (leaflet-src.js:229)
at Object.module.exports.map (map.js:233)
at new create (pubnub-mapbox.js:79)
at Object.window.eon.map (pubnub-mapbox.js:291)
at <anonymous>:2:19
at HTMLElement._createLocalRoot (polymer-mini.html:1998)
at HTMLElement._setupRoot (polymer-mini.html:1703)
I feel like I'm missing something very simple but I can't seem to catch my mistake. Any help would be greatly appreciated.
I was able to get eon-maps to render using the following:
Define a new eon-map element in eon.html page that contains the example code.
<link rel="stylesheet" type="text/css" href="./bower_components/mapbox.js/mapbox.css">
<script src="./bower_components/mapbox.js/mapbox.js"></script>
<script src="./bower_components/pubnub/dist/web/pubnub.min.js"></script>
<script src="./bower_components/eon-map/pubnub-mapbox.js"></script>
<dom-module id="eon-map">
<template>
<style type="text/css">
#map {
height: 200px;
}
</style>
<div id='map'></div>
</template>
<script>
Polymer({
is: 'eon-map',
ready: function() {
var channel = 'pubnub-mapbox';
var pub = new PubNub({
publishKey: 'your_pub_key',
subscribeKey: 'your_sub_key',
logVerbosity: true
});
var map = eon.map({
pubnub: pub,
id: 'map',
mbToken: 'your_mb_token',
mbId: 'your_mb_id',
channels: [channel],
debug: true
});
}
});
</script>
</dom-module>
Then, include eon.html in your root and use the eon-map element.
<link rel="import" href="./bower_components/polymer/polymer.html">
<!-- <link rel="import" href="shared-styles.html"> -->
<link rel="import" href="./bower_components/geo-location/geo-location.html">
<link rel="import" href="./bower_components/google-map/google-map.html">
<link rel="import" href="eon.html">
<eon-map></eon-map>

Polymer reflect functions across elements

I have a behavior that is shared across elements.
In a element i have a on-change="_toggle" switch.
In a second element i have the same code from the first element without the switch button. when the switch is active it reflect to the element containing the switch.
Q: how can i reflect the on-change="_toggle" function across all elements?
my code:
1.
<script>
LanguageBehavior = {
behaviors: [
Polymer.AppLocalizeBehavior
],
properties: {
language: {
value: 'sl',
reflectToAttribute: true
},
},
attached: function() {
this.loadResources(this.resolveUrl('/data/locales.json'));
},
_toggle: function() {
this.language = this.$.switch.checked ? 'en' : 'sl';
// This function is the problem?
}
};
</script>
2
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="../../bower_components/app-localize-behavior/app-localize-behavior.html">
<link rel="import" href="behavior.html">
<dom-module id="bazdara-element-1">
<template>
<style>
:host {
display: block;
}
</style>
{{localize('menu_2')}} // THIS CHANGES WITH THE SWITCH
<span title="english">🇬🇧 SI</span>
<paper-toggle-button on-change="_toggle" id="switch"></paper-toggle-button>
<span title="french">EN</span>
</template>
<script>
Polymer({
is: 'bazdara-element-1',
behaviors: [Polymer.AppLocalizeBehavior, LanguageBehavior],
});
</script>
</dom-module>
3
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/app-localize-behavior/app-localize-behavior.html">
<link rel="import" href="behavior.html">
<dom-module id="bazdara-element-2">
<template>
<style>
:host {
display: block;
}
</style>
{{localize('menu_2')}} // THIS Doesnt change
</template>
<script>
Polymer({
is: 'bazdara-element-2',
behaviors: [Polymer.AppLocalizeBehavior, LanguageBehavior],
});
</script>
</dom-module>
As each element will have its own copy of the behavior your approach is not going to work. Right now the only options i can come up with is:
keep both your elements in one common element and change the property there.
If you are planning to have all your elements in one single html file you can then change this feature in that html file and bind the property to all your elements.

Looking for different pattern match in app-route

I am using the Polymer CLI to create an app. I am utilizing Encapsulated Routing with Elements and Step 1. Get set up am trying to match the following patterns:
/analyze/:p1
/analyze/:p1/:p2
/analyze/:p1/:p2/:p3
That routes to 3 different web components.
For your <app-route> element, set the following attributes:
pattern = your desired route pattern
data = property binding to contain the parsed paths
In your case:
<app-route
pattern="/analyze/:p1/:p2/:p3"
data="{{routeData}}">
</app-route>
{{routeData}} will contain:
{
p1: 'a',
p2: 'b',
p3: 'c'
}
<head>
<base href="https://polygit.org/polymer+:master/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="app-route/app-route.html">
<link rel="import" href="paper-input/paper-input.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<app-route
route="{{route}}"
pattern="/analyze/:p1/:p2/:p3"
data="{{routeData}}"
tail="{{tail}}">
</app-route>
</template>
<script>
Polymer({
is: 'x-foo',
ready: function() {
this.route = {path: "/analyze/a/b/c/d/e/f"};
console.log('p1', this.routeData.p1);
console.log('p2', this.routeData.p2);
console.log('p3', this.routeData.p3);
console.log('tail', this.tail.path);
}
});
</script>
</dom-module>
</body>
jsbin

app-router not working imperatively way

I have this Polymer custom element:
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../bower_components/core-animated-pages/core-animated-pages.html">
<link rel="import" href="../../../bower_components/app-router/app-router.html">
<polymer-element name="custom-pages" attributes="selected">
<template>
<link rel="stylesheet" href="custom-pages.css">
<app-router id="router" bindRouter core-animated-pages transitions="cross-fade-all" trailingSlash="ignore">
<template repeat="{{page in pages}}">
<app-router path="{{page.path}}" import="{{page.url}}"></app-router>
</template>
</app-router>
</template>
<script>
(function() {
Polymer({
selected: 0,
pages: [{
path: "/home",
url: '../custom-home/custom-home.html'
}, {
path: "/about",
url: '../custom-about/custom-about.html'
}],
selectedChanged: function(oldValue, newValue) {
router = this.$.router;
router.go(this.pages[newValue].path);
}
});
})();
</script>
</polymer-element>
Elements custom-home and custom-about should be lazy loaded when "selected" change, but not is happening (no page is displayed).
You have a syntax error in your template definition, nested tags are to be app-route rather than app-routeR:
<app-router id="router" ...>
<template repeat="{{page in pages}}">
<!-- ⇓ superfluous r, nested are app-route -->
<app-router path="{{page.path}}" import="{{page.url}}"></app-router>
<!-- SHOULD BE: -->
<app-route path="{{page.path}}" import="{{page.url}}"></app-route>
</template>
</app-router>
Currently you have created a bundle of empty routers.
Plus, the documentation says:
If you use go(path, options) you should also set the mode to hash or pushstate on the router.
I am not sure if this affects your case, since you do not seem to pass options.
Hope it helps.