Запретить вызов родителя при вложенном ui-sref
Скажем, у меня есть вложенные DOM, и у каждого есть ui-sref
для разных состояний angular-ui-router
. Я хочу щелкнуть внешний, чтобы только оповещать о внешнем виде, и нажмите внутренний, чтобы только предупредить внутреннюю. В настоящее время, если я нажму внутренний, он будет предупреждать как внешнее, так и внутреннее состояние.
HTML:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="http://code.angularjs.org/1.2.13/angular.js" data-semver="1.2.13"></script>
<script data-require="[email protected]" data-semver="0.2.8" src="http://angular-ui.github.io/ui-router/release/angular-ui-router.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<a ui-sref="outer" style="width:300px;height:300px;background:yellow;">
Outer
<span ui-sref="inner" style="width:100px;height:100px;background:red;">Inner</span>
</a>
</body>
</html>
JavaScript:
var app = angular.module('plunker', ['ui.router']);
'use strict';
app.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider) {
$stateProvider
.state("outer", {
url: "/outer",
resolve: {
test: function() {
alert("Triggered state outer");
return true;
}
}
})
.state("inner", {
url: "/inner",
resolve: {
test: function() {
alert("Triggered state inner");
return true;
}
}
});
}]);
app.controller('MainCtrl', function($scope) {
});
Ссылка: http://plnkr.co/edit/yzgUAA3lLwkF9svzczl3?p=preview
Вопросы
-
Как предотвратить внутреннее, чтобы вызвать внешнее состояние?
-
Должен ли я реализовать какой-то stopImmediatePropagation
для внутренней DOM, чтобы он не вызывал родительский DOM ui-sref
?
-
Есть ли альтернативы? Может быть, используя $state.go
вручную?
ОБНОВЛЕНИЕ 1:
Я не могу изменить HTML из-за требования. Это просто упрощенная версия, потому что в моем коде внешний элемент очень большой, содержащий другие элементы.
Ответы
Ответ 1
Это работает
<a ui-sref="outer" style="width:300px;height:300px;background:yellow;">
Outer
<span ui-sref="inner" style="width:100px;height:100px;background:red;" ng-click="$event.stopPropagation()">Inner</span>
</a>
Я не знал, что вы можете добавить ng-click="$event.stopPropagation()"
в тот же элемент, что и ui-sref
Ответ 2
ИСПОЛЬЗУЙТЕ ЭТО...
<a ui-sref="outer" style="width:300px;height:300px;background:yellow;">
Outer
<span ui-sref="inner" style="width:100px;height:100px;background:red;"
ng-click="$event.stopPropagation()">Inner</span>
</a>
Ответ 3
Проблема заключается не в вашем javascript-коде, а в html
<a ui-sref="outer" style="width:300px;height:300px;background:yellow;">
Outer
<span ui-sref="inner" style="width:100px;height:100px;background:red;">Inner</span>
</a>
когда вы нажимаете в любом месте тега, вызывается внешнее состояние.
ваш
Inner
находится внутри тега, поэтому этот элемент html связан как с ui-sref = "inner", так и с ui-sref = "external"
приведенный ниже код должен решить вашу проблему
<a ui-sref="outer" style="width:300px;height:300px;background:yellow;">
Outer
</a>
<span ui-sref="inner" style="width:100px;height:100px;background:red;">Inner</span>
Ответ 4
Должен ли я реализовать какой-то stopImmediatePropagation
для внутренней DOM, чтобы он не запускал родительский DOM ui-sref
?
Да, точно.
В качестве альтернативы вы можете изменить свой HTML-код, чтобы у него не было отношения родительский/дочерний.
Ответ 5
Добавить функцию остановки события/события, предотвращающую дефолт по умолчанию во внутреннем состоянии:
$stateProvider.state("outer", {
url: "/outer",
resolve: {
test: function() {
alert("Triggered state outer");
return true;
}
}
}).state("inner", {
url: "/inner",
resolve: {
test: function() {
alert("Triggered state inner");
//$event.stopPropagation();
$event.preventDefault();
return true;
}
}
})
Обновление 1: Я попробовал демонстрацию плункера и доступно $event. По angular doc также для
Объект события доступен как $event. DEMO Angular doc
Обновление 2: Выше работает, если u сначала нажимает внешний div, но это не решение. Я согласен. Итак, вот еще одно решение, которое работает. проверяя statechangestart области и сохраняя последнее имя состояния в var и проверяя, не является ли его внутреннее событие eventdefault;
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
var laststate = "";
$scope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams) {
//alert(laststate);
if (laststate == "inner") {
event.preventDefault();
}
laststate = toState.name;
});
});
DEMO Plunker
Ответ 6
Для совершенно другой цели у меня была директива stopEvent, ожидающая использования для вложенной цели ui-sref.
<a ui-sref="outer">
Outer
<span ui-sref="inner" stop-event>Inner</span>
</a>
Это директива
app.directive('stopEvent', function () {
return {
restrict: 'A',
link: function (scope, element, attr) {
element.bind('click', function (e) {
e.stopPropagation();
});
}
};
});