Как программно создавать URL-адреса с помощью AngularJS
В настоящее время я играю с рамкой AngularJS. Я использую службу $route для глубокой привязки к моему одностраничному приложению.
Теперь я хотел бы перемещаться внутри своего приложения, скажем, путем изменения только части поиска текущего URL-адреса. Это легко сделать с помощью службы $location в JavaScript, но как я могу построить атрибут href из текущего маршрута только с заменой части поиска?
Должен ли я делать это вручную или есть способ AngularJS для него?
Добавлено:
Конечно, служба $location имеет все методы для вычисления таких URL-адресов. Но я не могу использовать его, потому что $location также перемещает окно браузера на новый URL.
Есть еще одно осложнение при создании URL-адресов вручную: нужно проверить, используется ли старый # -метод или новый API истории. В зависимости от этого URL должен содержать # -знак или нет.
Ответы
Ответ 1
Начиная с версии 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'] });
Ответ 2
После ответа Роберта я нашел функции в Angular.js. Это buildUrl, forEachSorted и sortedKeys. builUrl также использует функции 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('&');
}
Ответ 3
Как вы можете видеть в исходном коде здесь (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, возможно, вы можете скопировать эти функции из источника в свой код и сделать для этого свой собственный сервис.