Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programmatically create URLs with AngularJS

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.

like image 358
Marc Avatar asked Oct 09 '12 21:10

Marc


3 Answers

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'] });
like image 177
Delian Mitankin Avatar answered Oct 17 '22 19:10

Delian Mitankin


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('&');
}
like image 13
synergetic Avatar answered Oct 17 '22 17:10

synergetic


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.

like image 3
Robert Avatar answered Oct 17 '22 17:10

Robert