polymerelements / app-route Goto Github PK
View Code? Open in Web Editor NEWA modular client-side router
Home Page: https://www.polymer-project.org/1.0/articles/routing.html
A modular client-side router
Home Page: https://www.polymer-project.org/1.0/articles/routing.html
Inside carbon-route (in __tryToMatch
), this.data
is set just before this.tail
, as you see here.
This results in the inability to do routing logic on data changes because the current tail is incorrect (old).
For example, if you have a single route of /:page
and use the data to control iron-pages, like so:
<iron-pages selected="{{routeData.page}}" attr-for-selected="data-route">
<my-page data-route="contact" route="{{route.tail}}"></my-page>
</iron-pages>
my-page
will be selected as soon as routeData.page
changes, but at that point, route.tail
is the old tail. So, imagine in my-page
, we do:
observers: [
'_onActive(active)'
],
_onActive: function(active) {
if(active) {
this.set('route.path', '/default');
}
}
It will be attempting to set /theOldPage/default
rather than /contact/default
.
This can probably be worked around by observing route.prefix
and checking if it equals /contact
before setting the path. However, we should not know or care what path we are in, that is upto the parent to decide, so this workaround would be incorrect.
Would it be an issue to swap them around? Or do you know a better solution?
As a Polymer app author,
when I use carbon-route
and a routing ServiceWorker
,
I want the ServiceWorker
to be aware of my app's routes,
so that I only have to declare them in one place.
This issue is intended for design discussion about how to make sure that ServiceWorker
s that care about routing don't have be configured in a redundant way for Polymer apps that use carbon-route
.
Could you create demo for Progressive Web App?
I think this is something that Tedium can fix for us fairly easily, but it needs to be done.
Once a route matches, the global path may change such that the route's route
property does not change. This results in active
remaining true
for routes that do not match the global path.
As of #4 there will no longer be a thing called carbon-router
. Should this repository continue to be called carbon-router
? Should carbon-route
, carbon-route-converter
and carbon-location
live together or in separate repositories?
As an author looking for a router,
when I review carbon-route
as a potential solution,
I want to read a brief, approachable document that explains how to use it,
so that I can quickly get up to speed with how it will work in my app.
In the Polymer routing guide, it mentions that questions tagged "carbon-route" on stackoverflow will be watched:
https://www.polymer-project.org/1.0/articles/routing.html
However, I am not able to tag questions with this tag because the tag does not yet exist, and at least 1500 reputation is required to create a new tag (e.g. currently I only have ~150 reputation).
It should be possible to tag stackoverflow.com questions with carbon-route without requirement for 1500 reputation.
It is not possible to tag a stackoverflow.com question with carbon-route without having at least 1500 reputation.
The question that I'd like to tag with carbon-route is:
https://stackoverflow.com/questions/36670748/activating-default-route-if-no-other-carbon-route-active
all
The customized jsbin will need a url-bar element though, as jsbins run in iframe by default, so this is blocked by #46
This needs to be done across all relevant source files.
e.g. https://travis-ci.org/PolymerElements/carbon-route/builds/119160016
Doesn't look related to the timeout bug #64
As an app author,
when I add routing to my stateful app,
I want to configure routing to treat hash changes as though they are path changes,
so that I can deploy my app to a non-configurable static web server.
It is common for client-side JavaScript routers to allow the hash
of a URL as a stand-in alternative to path
. This allows a router to be used in cases when the author is deploying to a static web server (such as the Github Pages use case). It would be nice if carbon-location
enabled this use case via a boolean property (or similar).
Need to touch base with @azakus on this, as I don't have a sauce account afaict.
This is because of the _skipMatch
property, causing upstream routes to ignore changes to their tail
properties, even if they're legitimate. We should be able to get rid of _skipMatch
or double checking the values of data
and tail
after we set _skipMatch
to false in __tryToMatch
.
To be located at the top of carbon-route.html
.
This won't land until the extends
branch in Polymer is merged, but we should test it out to be confident that this should work.
With carbon-route, we can't distinguish between forward navigation and backward navigation. This would be useful so we could restore scroll position when navigating back to a page, which is what the browser does natively.
There may be an obvious approach to this that I'm missing, but I don't understand the timing. If we use plain <a>
tags to navigate, <carbon-route>/<carbon-location>
handle the changes and ultimately (via <iron-location>
) call pushState
or replaceState
. So the component that consumes the route has no ability to specify a state object.
How could we handle this? Maybe <carbon-route>
could expose a callback just before deactivating a route, so the active component could supply its current state. And all of the active carbon-routes could somehow... integrate their states into a big state glob before calling pushState/replaceState.
This doesn't sound pretty, but the other alternative is probably "app does a bunch of magic and still gets it wrong sometimes."
It seems like it would be nice to have an exact
boolean attribute that would exclude tail matching and require that the whole URL matches the remaining path. For instance, if I have a list and show for users I might want something like:
<carbon-route pattern="/users" active="{{listUsers}}" exact route="[[route]]"></carbon-route>
<carbon-route pattern="/users/:id" active="{{showUser}}" tail="{{userParams}}" route="[[route]]"></carbon-route>
Without exact
, there is never a circumstance in which the first route is matched but the second isn't.
If I'm misunderstanding the intended way to structure these routes (entirely probable) feel free to show me how I might approach the above in a more as-intended way. ๐
As an app author,
when I add routing to my app with snowflake requirements,
I want access to the url space configuration,
so that I can make carbon-route
s fit my use case.
A trailing slash in a pattern currently means that you want to match a slash followed by the empty string.
This is counterintuitive, and an easy place to make mistakes. However, it's also useful, for specifically matching paths that end with a trailing slash.
Not sure if by design or a known limitation:
I have a parent route with a :page
data property and a subroute with an :id
property.
<carbon-location route="{{route}}"></carbon-location>
<carbon-route
route="{{route}}"
pattern="/:page"
data="{{routeData}}"
tail="{{subroute}}">
</carbon-route>
<carbon-route id="subrouter"
route="{{subroute}}"
pattern="/:id"
data="{{subrouteData}}">
</carbon-route>
If I update the data
property of a subroute the browser location bar won't propagate, if the subroute is not active/matched.
Original URL: http://localhost:8000/somePage
this.$.subrouter.data = {id:2};
New URL: http://localhost:8000/somePage/2
Original URL = New URL = http://localhost:8000/somePage
This seems to be due to the fact that the subroute is not active and __updatePathOnDataChange will bail out early.
Workaround:
change the tail.path
of the parent carbon-route
instead of the data
property of the subroute.
As a user of carbon-route, I want to be able to react when none of my carbon-routes in a section of code match the current path. For example, I may want to display a 404 page, or redirect to my home page.
One solution may be adding the concept of being given a selection that doesn't match to <iron-pages>
.
All demo pages work only on Chrome, e.g.
https://www.polymer-project.org/1.0/articles/routing/demo1.html
I noticed this TODO
in the code as I was stepping through it.
I propose that we take one of two possible actions:
~
range, should be ^
range.description
field.main
field.moduleType
, ignore
etc.)iron-page-url
is going to be renamed to iron-location
. References to iron-page-url
need to be updated to refer to iron-location
.
The route and hash are not in sync.
In the example below, the expected outcome is that the hash part of the url is in sync with the selected tab.
loading the page without already setting the # part (e.g. just localhost
instead of localhost/#home
) causes the url to be out of sync (no change in the url is observed when selecting new tab).
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/neon-animation/neon-animated-pages.html">
<link rel="import" href="../bower_components/neon-animation/neon-animations.html">
<link rel="import" href="../bower_components/carbon-route/carbon-location.html">
<link rel="import" href="../bower_components/carbon-route/carbon-route.html">
<link rel="import" href="../bower_components/paper-scroll-header-panel/paper-scroll-header-panel.html">
<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html">
<link rel="import" href="../bower_components/paper-tabs/paper-tabs.html">
<link rel="import" href="../bower_components/paper-tabs/paper-tab.html">
<dom-module id="test-carbon">
<template id="app">
<!-- include the style module by name -->
<style>
:host {
display: block;
}
#page {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
<carbon-location route={{route}} use-hash-as-path></carbon-location>
<carbon-route route="{{route}}" pattern=":tab" data="{{data}}"></carbon-route>
<paper-scroll-header-panel id="page" condenses>
<paper-toolbar class="tall">
<div class="title">Title</div>
<div class="bottom">
<paper-tabs selected="{{data.tab}}" attr-for-selected="name">
<template is="dom-repeat" items="[[sections]]" as="section">
<paper-tab name="[[section.id]]"><span>[[section.title]]</span></paper-tab>
</template>
</paper-tabs>
</div>
</paper-toolbar>
<div class="content">
<neon-animated-pages attr-for-selected="data-route" relative-position selected="[[data.tab]]" entry-animation="fade-in-animation" exit-animation="fade-out-animation">
<div data-route="home">
<h3>Home</h3>
<p>Home content</p>
</div>
<div data-route="dashboard">
<h3>Dashboard</h3>
<p>Dashboard content</p>
</div>
</neon-animated-pages>
</div>
</paper-scroll-header-panel>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'test-carbon',
properties: {
route: {
type: Object,
notify: true
},
data: {
type: Object,
value: {
tab: 'dashboard'
}
},
sections: {
type: Array,
value: function() {
return [{
id: 'home',
title: 'home'
}, {
id: 'dashboard',
title: 'dashboard'
}]
}
}
}
});
})();
</script>
</dom-module>
Currently, the iron-page-url
dependency in bower.json
points to a WIP branch called iron-query-params
. For release, I propose that we change this to point to a specific semver release of iron-page-url
. In order to accomplish this, we should get https://github.com/PolymerElements/iron-page-url/tree/iron-query-params merged into master
on that repo ASAP.
From @ebidel on October 31, 2015 18:48
Currently the element fires route-change
on window
(here), but to leverage polymer event handlers, it's nice to catch this event on the element itself. I've modified carbon-router locally with this change. Would be good to support this:
<dom-module id="carbon-router">
<script>
Polymer({
is: 'carbon-router',
behaviors: [
Polymer.CarbonRoutingBehavior,
Polymer.CarbonRoutingRootBehavior
],
properties: {
route: {
notify: true,
observer: '_routeChanged'
},
matches: {
value: ':base'
}
},
_routeChanged: function() {
this.fire('route-change', {route: this.route});
}
});
</script>
</dom-module>
Copied from original issue: PolymerElements/carbon-elements#4
The mapping is very elegant if the URL scheme matches the code structure. For example (from https://www.polymer-project.org/1.0/articles/routing.html#example):
<carbon-route route="{{route}}" pattern="/tabs/:tabName" data="{{data}}">
</carbon-route>
<neon-animated-pages selected='{{data.tabName}}' attr-for-selected='key'>
<neon-animatable key='foo'>Foo Page Here</neon-animatable>
<neon-animatable key='bar'>Bar Page Goes Here</neon-animatable>
<neon-animatable key='baz'>Baz Page, the Best One of the Three</neon-animatable>
</neon-animated-pages>
It's getting considerable more complex if the key
can't be directly extracted from the location (e.g. because an existing URL schema needs to be preserved).
For example, given these locations:
Mapping would require something along these lines:
<carbon-route route="[[route]]" pattern="/groups" active="{{isAll}}"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId" active="{{isProfile}}"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId/members" active="{{isMembers}}"></carbon-route>
<iron-pages attr-for-selected="key" selected="getKey(isAll, isProfile, isMember)">
<div key="all">...</div>
<div key="profile">...</div>
<div key="members">...</div>
</iron-pages>
...
/** Map the various flags for the `selected` property of iron-pages: */
getKey: function(isAll, isProfile, isMembers) {
// Workaround for issue #61: match most specific first
if (isMembers) return 'members';
if (isProfile) return 'profile';
if (isAll) return 'all';
return 'default';
}
As a user, I'd love to get the key directly from the routing elements. For example, something along these lines:
<carbon-selected-route key="{{key}}">
<carbon-route route="[[route]]" pattern="/groups/:groupId/members" key="members"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups/:groupId" key="profile"></carbon-route>
<carbon-route route="[[route]]" pattern="/groups" key="all"></carbon-route>
</carbon-selected-route>
The surrounding element would then return the key of the route that matching first.
I can have a route like /article/1#subsection
It would be nice with a explanation on how to load that route and still make it scroll to the #subsection like it would had I used actual pages instead of routing.
That's a substantial application for being just demo.
Any inclinations to downsizing it, to increase comprehensibility? I've personally my trouble with it and am stripping everything unnecessary out of it.
Though I appreciate having a full application as a demo.
To be located at the top of carbon-route-converter.html
.
Hi, I made this small change, but maybe it should be standard feature:
<carbon-route route="{{route}}"
ws.title = document.title; // Global
...
properties:{
route: {
observer: '_setTitle'
}
},
...
_setTitle: function(newValue, oldValue){
document.title = ws.title + newValue.path;
},
Or is there a better way to do this.
Instead, we should rely on Polymer's new element inheritance features to enable shared implementation.
The current demos have a mix of files going back a number of months. Need to clean that out and show off the most recent rev of the code.
Add a pre-route handler that is fired everytime a route is tested, it should receive the route parameters that would be set, if the pre-route handler fails.
pre-route handler would fail by passing back a new route object or path (redirect to login page for example) basically, if return is not falsey it should be a failed pre-route check.
This way the demos will make sense in environments like the elements catalog.
Blocked by #46
Subject says it all. It would be nice to find Carbon elements on elements.polymer-project.org
Hello,
I watched the last Polycast about lazy loading. In the Polycast, Rob lazy load the elements before changing the route using page.js. It would be great to be able to run some logic before changing the page using carbon-route.
The url-bar element from the carbon-route explainer is useful for our demos. It detects when it's running in an iframe and draws a helpful read-only live view of the URL bar. When it's not running in an iframe it's invisible.
We should import it into iron-demo-helpers or someplace similar and use it in these demos and in the iron-location demos.
The readme says that (carbon location) https://elements.polymer-project.org/elements/carbon-route-converter?foo=bar&baz=qux produces a route of:
{
prefix: '',
path: '/elements/carbon-route-converter'
}
Thus ignoring queries.
But (carbon route convertor) says that:
https://elements.polymer-project.org/elements/carbon-route-converter?foo=bar&baz=qux:
has a route of:
{
prefix: '',
path: '/elements/carbon-route-converter',
queryParams: {
foo: 'bar',
baz: 'qux'
}
}
I assume that it only has this route object when using iron-location and not carbon-location but that is not clear.
Also, why does
<carbon-route-converter
path="{{path}}"
query-params="{{queryParams}}"
route="{{route}}">
</carbon-route-converter>
<carbon-route route='{{route}}' pattern='/:page' data='{{data}}'>
carbon-route-convertor need the queryParams at all, when carbon-location assumes a route without query params (unless the use-hash-as-path is used)?
I think this could be made more clear, and the readme could benefit from more examples using queries which is actually not that uncommon a use-case.
Not sure if this is by design or a known issue. I put carbon-route
and carbon-location
into a custom element. I added a observer
to check if the page
parameter is valid and if not I reset it, so that the user is redirected to a valid path.
So if I open the path: http://localhost:8000/some_invalid_path
I should get redirected to http://localhost:8000
Browser location bar should be updated
Browser location bar is NOT updated
I am not sure how to do a demo in jsbin
<dom-module id="my-router">
<template>
<carbon-location route="{{route}}" ></carbon-location>
<carbon-route
route="{{route}}"
pattern="/:step"
data="{{page}}"
tail="{{tail}}">
</carbon-route>
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'my-router',
properties: {
page: {
type:Object,
value: function(){ return {};},
},
},
observers: [
'_changeRoute(page)',
],
_changeRoute: function(page) {
// check if page is valid if not redirect
this.page = {};
},
});
})();
</script>
</dom-module>
As far as I can tell the reason is that in the _updateUrl method in iron-location
the flag _initialized
is false because iron-location
has not been attached yet.
The only workaround is to use async
:
_changeRoute: function(page) {
// check if page is valid if not redirect
this.async(function() {
this.page = {};
});
},
This issue is here to facilitate discussion on an API naming topic.
The proposal is that carbon-route
and the route
property of same embody distinct concepts respectively, and so either carbon-route
should be renamed, or route
should be renamed.
Please discuss possible alternatives or arguments against the proposal in this issue!
We get a message in the iframe saying that it can't find the path /foo/, suggesting that the page reloaded/redirected during testing.
I've only seen this failure in Chrome.
As a custom element author,
when I extend carbon-route
and friends,
I want to assume that queryParams
will gracefully handle array properties,
so that I do not need to implement support myself.
Currently, we observe for sub-property changes on queryParams
in carbon-route
, but we do not actually support handling splices. In fact, splice changes will result in undefined behavior. Right now, this isn't a problem because we do not deserialize arrays in iron-query-params
. However, we should support splices in the long-run so that we are not locked into iron-query-params
implementation for this kind of thing.
This is an open design question that has not settled. Please discuss pros, cons and alternatives in this issue.
To be located at the top of carbon-location.html
.
Object.assign
is used in .__routeQueryParamsChanged, which is not supported in IE11 (ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign). Is there an alternative we can use?
Router should work in IE11.
Router doesn't work in IE11.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.