Currently I am toying with the AngularJS framework. I'm using the $route service for deep linking into my single-page application.
Now I would like to navigate inside my application, say, by changing just the search part of the current URL. It is easy to do using the $location service in JavaScript, but how can I construct an href attribute from the current route with just the search part replaced?
Do I have to do it by hand or is there an AngularJS way for it?
Added:
Of course, the $location service has all methods to calculate such URLs. But I cannot use it because $location does also navigate the browser window to the new URL.
There is another complication with creating URLs by hand: One has to check whether the legacy #-method or the new History API is used. Depending on this, the URL has to include a #-sign or not.
Starting from v1.4 you can use $httpParamSerializer for that:
angular.module('util').factory('urlBuilder', function($httpParamSerializer) {
function buildUrl(url, params) {
var serializedParams = $httpParamSerializer(params);
if (serializedParams.length > 0) {
url += ((url.indexOf('?') === -1) ? '?' : '&') + serializedParams;
}
return url;
}
return buildUrl;
});
Usage:
To produce http://url?param1=value1¶m2=value2_1¶m2=value2_2
call it with:
urlBuilder('http://url', { param1: 'value1', param2: ['value2_1', 'value2_2'] });
Following Robert's answer, I found the functions in Angular.js. They are buildUrl, forEachSorted, and sortedKeys. builUrl also uses isObject and toJson functions, which are public, so they must be changed to angular.isObject and angular.toJson respectively.
function forEachSorted(obj, iterator, context) {
var keys = sortedKeys(obj);
for (var i = 0; i < keys.length; i++) {
iterator.call(context, obj[keys[i]], keys[i]);
}
return keys;
}
function sortedKeys(obj) {
var keys = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys.sort();
}
function buildUrl(url, params) {
if (!params) return url;
var parts = [];
forEachSorted(params, function (value, key) {
if (value == null || value == undefined) return;
if (angular.isObject(value)) {
value = angular.toJson(value);
}
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
});
return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
}
As you can see in the source code here (v.1.1.0):
https://github.com/angular/angular.js/blob/v1.1.0/src/ngResource/resource.js#L228
and here:
https://github.com/angular/angular.js/blob/v1.1.0/src/ngResource/resource.js#L247
Angularjs doesn't use internally encodeURIComponent for managing URI strings but neither make available the used functions. These functions are internal to the module (what I think is a pity).
If you want to manage your URIs in exactly the same way that AngularJS, maybe you can copy these functions from the source to your code and make your own service for that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With