32

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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Marc
  • 4,327
  • 4
  • 30
  • 46
  • Do you mean like, taking this route: /something/16 and making a new one like /something/30 ? – doubledriscoll Oct 10 '12 at 17:53
  • Yes, something like that. Or making #/something/30?x=4 into #/something/30?x=5 – Marc Oct 10 '12 at 20:14
  • You could track the pertinent parts of your URL in the $rootScope, and then have a service you can inject to look at those values and change the URL. ... just spitballing. – Ben Lesh Oct 11 '12 at 15:01

3 Answers3

27

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&param2=value2_1&param2=value2_2 call it with:

urlBuilder('http://url', { param1: 'value1', param2: ['value2_1', 'value2_2'] });
Delian Mitankin
  • 3,691
  • 26
  • 24
  • hi, can i do this in angular 6? because i don't see any documentation on httpparamserializer in angular 6 – mhfour May 16 '19 at 08:46
13

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('&');
}
synergetic
  • 7,756
  • 8
  • 65
  • 106
3

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.

Robert
  • 31,925
  • 8
  • 35
  • 33
  • 2
    Your links are broken because you didn't link to a specific commit :-( – Dan Apr 08 '14 at 17:20
  • @user37078 thanks. I edited the post, but I don't know how URI strings are managed in the latest AngularJS version so, maybe, the answer is not valid anymore. – Robert Apr 09 '14 at 16:08