Как удалить ранее предоставленный необязательный параметр при изменении состояния с помощью ui-router
У меня есть состояние с необязательным параметром запроса. Я думал, что это работает нормально, но я обнаружил, что после указания необязательного параметра он сохраняется с этой точки, когда я перехожу в одно и то же состояние с другими параметрами, если только необязательный параметр явно не удален.
Есть ли способ убедиться, что необязательный параметр удаляется из-за изменений состояния?
Это пример того, как я хочу изменить состояние (тест a и тест b), но оказывается, что я должен использовать версию test d из-за сохранения необязательного параметра, если он был использован ранее,
<a ui-sref="test({req: 'a'})">test a</a><br/>
<a ui-sref="test({req: 'b'})">test b</a><br/>
<a ui-sref="test({req: 'c', opt: 'here'})">test c and opt</a><br/>
<a ui-sref="test({req: 'd', opt: undefined})">test d and explicity without opt</a>
Это похоже на то, как настроено мое состояние:
$stateProvider.state('test', {
url: '/{req}?opt',
params: {
opt: {value: null, squash: true}
},
template: '<h1>req = {{req}}</h1>' +
'<h1>opt = {{opt}}</h1>',
controller: function($scope, $stateParams) {
$scope.req = $stateParams.req;
$scope.opt = $stateParams.opt;
}
})
Вот jsfiddle. Нажмите на первые две ссылки, и он работает так, как ожидалось, но как только вы нажмете на 3-ей ссылке, а затем щелкните по одной из первых двух ссылок, вы увидите, что дополнительный параметр сохраняется, хотя он опущен в первые две ссылки.
Я бы предпочел, чтобы не было явно reset необязательный параметр и действительно ли он работал, если он является необязательным.
Любые идеи? Так ли оно работает? Если да, есть ли способ заставить его работать так, как я хочу? Или я обнаружил ошибку?
Обновление
Похоже, что сохранение необязательного параметра "как было разработано" на основе одного из приведенных ниже ответов. Тем не менее, я по-прежнему смотрю на эффективное обходное решение, если это возможно. Я перехожу в состояние из множества мест в моем приложении, и 99% из них не указывают необязательный параметр. Я бы предпочел не изменять все эти переходы и не знать о необязательном параметре, а вместо этого указывать только необязательный параметр в 1% времени, в котором я нуждаюсь.
Я попытался создать два состояния "test" и дочерний "test.opt", а затем перейти к "тестированию" в обычном режиме (например, "test a" и "test b" ), и только переход к "test.opt", когда я указываю необязательный параметр. Тем не менее, у меня есть решение, которое вызывает вызов для отдыха, и ему нужно знать, установлен ли параметр opt, поэтому он не работает, поскольку решение не может получить доступ к "opt" из дочернего элемента.
Обновление # 2
Я также попытался создать дубликат состояния "test" с именем "testopt", и в этом случае единственное отличие - параметр "opt". Однако очевидно, что ui-router не может различать два URL-адреса, которые отличаются только параметром запроса, и поэтому он все же пытается перейти на "тест", даже если opt param является частью URL-адреса.
Ответы
Ответ 1
Просто добавьте опцию ui-sref-opts inherit = false к вашим ссылкам:
<a ui-sref="test({req: 'a'})" ui-sref-opts="{inherit: false}">test a</a><br/>
<a ui-sref="test({req: 'b'})" ui-sref-opts="{inherit: false}">test b</a><br/>
<a ui-sref="test({req: 'c', opt: 'here'})" ui-sref-opts="{inherit: false}">test c and opt</a><br/>
<a ui-sref="test({req: 'd', opt: undefined})" ui-sref-opts="{inherit: false}">test d and explicity without opt</a>
Тема, которая документирует этот запрос и реализацию этой функции: https://github.com/angular-ui/ui-router/issues/376
---- EDIT ----
Так как вышеупомянутое решение не кажется идеальным, поскольку оно также требует обновления (и поддержания) каждого из якорей si-sref для установки желаемого поведения, другим решением может быть переопределение метода состояния go(...)
для установки inherit
опция false по умолчанию. Хотя я не уверен, что это рекомендуемый шаблон, чтобы сделать это, измените свой .config на следующее:
.config(['$stateProvider', '$provide', function ($stateProvider, $provide) {
$stateProvider.state('test', {
url: '/{req}?opt',
params: {
opt: {value: null, squash: true}
},
template: '<h1>req = {{req}}</h1>' +
'<h1>opt = {{opt}}</h1>',
controller: function($scope, $stateParams) {
$scope.req = $stateParams.req;
$scope.opt = $stateParams.opt;
}
});
$provide.decorator('$state', function ($delegate) {
var state = $delegate;
state.baseGo = state.go;
var go = function (to, params, options) {
options = options || {};
if (angular.isUndefined(options.inherit)) {
options.inherit = false;
}
this.baseGo(to, params, options);
};
state.go = go;
return $delegate;
});
}])
Ответ 2
У меня была та же проблема, из-за наследования по умолчанию параметров...
Чтобы завершить предыдущий ответ, синтаксис для вызова JS:
$state.go('new state', {pararemeters... } , {inherit:false});