Как программно создавать URL с помощью AngularJS
В настоящее время я играю со структурой AngularJS. Я использую сервис $route для глубоких ссылок на мое одностраничное приложение.
Теперь я хотел бы перемещаться внутри моего приложения, скажем, изменяя только часть поиска текущего URL. Это легко сделать с помощью службы $location в JavaScript, но как я могу создать атрибут href из текущего маршрута с заменой только части поиска?
Нужно ли делать это вручную или есть способ AngularJS для этого?
Добавлено:
Конечно, у службы $location есть все методы для вычисления таких URL. Но я не могу использовать его, потому что $location также перемещает окно браузера к новому URL.
Существует еще одна сложность при создании URL-адресов вручную: необходимо проверить, используется ли устаревший #-метод или новый History API. В зависимости от этого, URL должен содержать знак # или нет.
3 ответа
Начиная с версии 1.4 вы можете использовать для этого $ httpParamSerializer:
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;
});
Использование:
Производить http://url?param1=value1¶m2=value2_1¶m2=value2_2
позвоните с помощью:
urlBuilder('http://url', { param1: 'value1', param2: ['value2_1', 'value2_2'] });
После ответа Роберта я нашел функции в Angular.js. Это buildUrl, forEachSorted и sortedKeys. buildUrl также использует функции isObject и toJson, которые являются открытыми, поэтому их необходимо изменить на angular.isObject и angular.toJson соответственно.
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('&');
}
Как вы можете видеть в исходном коде здесь (v.1.1.0):
https://github.com/angular/angular.js/blob/v1.1.0/src/ngResource/resource.js#L228
и здесь:
https://github.com/angular/angular.js/blob/v1.1.0/src/ngResource/resource.js#L247
Angularjs не использует внутренне encodeURIComponent для управления строками URI, но ни делает доступными используемые функции. Эти функции являются внутренними по отношению к модулю (что я считаю жалким).
Если вы хотите управлять своими URI точно так же, как AngularJS, возможно, вы можете скопировать эти функции из исходного кода в свой код и создать для этого свой собственный сервис.