I replaced PageJS routing in our application with app-location
and app-route
, and everything seems to be working except the query parameters. I noticed it can only read URLs like host?param1=val1#/view
, not host#view?param1=val1
how PageJS used to.
Upon further digging, I discovered that this is actually an RFC standard. I find it odd that PageJS and Angular can use the nonstandard query string format.
Is there a way to use the query-params
attribute of app-route
to read the nonstandard query parameters for backward compatibility?
The non-standard form works in PageJS because PageJS manually parses the query string from the URL by extracting the text that follows ?
and then parsing that for any hashes that need to be separated out. Angular might do something similar. On the other hand, <app-location>
(and <iron-location>
) uses the platform's window.location.search
to fetch the query parameters.
If you need to stick with <iron-location>
, you could add backward compatible support by monkey-patching <iron-location>._urlChanged()
, which is responsible for parsing the URLs for <app-location>
.
Monkey-patched <app-location>
:
Polymer({
is: 'my-app',
ready: function() {
this._setupAppLocation();
},
_setupAppLocation: function() {
// assumes <app-location id="location">
const ironLocation = this.$.location.$$('iron-location');
if (!ironLocation) return;
ironLocation._urlChanged = function() {
this._dontUpdateUrl = true;
this.path = window.decodeURIComponent(window.location.pathname);
if (window.location.hash.includes('?')) {
const parts = window.location.hash.split('?');
this.hash = window.decodeURIComponent(parts[0].slice(1));
this.query = parts[1];
// Prepend other query parameters found in standard location
if (window.location.search) {
this.query = window.location.search.substring(1) + '&' + this.query;
}
} else {
this.query = window.location.search.substring(1);
}
this._dontUpdateUrl = false;
this._updateUrl();
};
}
});
Alternatively, you could switch to a Polymer element that supports parsing query parameters in either form out of the box. I recommend <nebula-location>
(which uses QS
as its query string parser).
Example usage of <nebula-location>
:
<nebula-location data="{{locationData}}"></nebula-location>
<div>foo=[[locationData.queryParams.foo]]</div>
<a href="[[rootPath]]#view?foo=123">#view?foo=123</a>
<a href="[[rootPath]]?foo=123#view">?foo=123#view</a>