Предотвращение вызова родителя при вложенном ui-sref

18

Скажем, у меня есть вложенные 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="angular.js@1.2.x" src="http://code.angularjs.org/1.2.13/angular.js" data-semver="1.2.13"></script>
    <script data-require="ui-router@0.2.8" 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) {
});

Ссылка: Ссылка

Вопросы

  1. Как предотвратить внутреннее, чтобы вызвать внешнее состояние?

  2. Должен ли я реализовать какой-то stopImmediatePropagation для внутренней DOM, чтобы он не вызывал родительский DOM ui-sref ?

  3. Есть ли альтернативы? Возможно, используя $state.go вручную?

ОБНОВЛЕНИЕ 1:

Я не могу изменить HTML из-за требования. Это просто упрощенная версия, потому что в моем коде внешний элемент очень большой, содержащий другие элементы.

    
задан HP. 05.03.2014 в 07:12
источник

6 ответов

6

Это работает

<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

    
ответ дан HP. 08.03.2014 в 06:22
источник
  • Это работает, но я, кажется, получаю всю перезагрузку страницы, что, вероятно, не является желаемым поведением ... конечно, не для меня. –  Lewis 15.01.2015 в 13:46
  • ui-sref обновляет элемент href тега a, он не влияет на событие click. Как и в случае с jQuery, вы можете $ ('a'). Attr ('href', 'http://example.com') .on ('click', (e) => {/ * something * /}) –  itanex 06.02.2018 в 19:55
35

ИСПОЛЬЗУЙТЕ ЭТО ...

 <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>
    
ответ дан David_DD 14.03.2014 в 07:14
источник
  • Ваш кунг-фу strong Давид. –  Michael Cole 23.05.2015 в 20:07
  • У меня был похожий случай, но вместо внутренней ссылки мне пришлось вызвать функцию. Использование только $ event.stopPropagation () все еще вызывало навигацию. Добавление $ event.preventDefault () устраняет проблему. Я получил вдохновение от stackoverflow.com/a/25636705/2487876 –  CapK 25.10.2016 в 12:31
  • Очень сильная правда. Престижность к вам! –  SolidSmile 19.12.2016 в 21:55
  • Мне нравится простота этого решения. Это отлично подходит для прототипирования и простых элементов. было бы лучше иметь специализированный атрибут, такой как stopEvent выше –  itanex 06.02.2018 в 19:52
2

Для совершенно другой цели у меня была директива 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();
      });
    }
  };
});
    
ответ дан Christiaan Westerbeek 11.04.2017 в 10:32
источник
  • Невероятный ответ для меня! Спасибо!!! –  Canet Robern 27.03.2018 в 13:18
0
  

Должен ли я реализовать какой-то stopImmediatePropagation для внутренней DOM, чтобы он не вызывал родительский DOM ui-sref ?

Да, точно.

В качестве альтернативы вы можете изменить свой HTML-код, чтобы у него не было отношения родительский / дочерний.

    
ответ дан Scimonster 07.03.2014 в 07:38
источник
0

Добавить функцию остановки события / события, предотвращающую дефолт по умолчанию во внутреннем состоянии:

  $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. В соответствии с угловым документом также для
 Объект события доступен как $ event. DEMO Угловой документ

Обновление 2: Выше работает, если сначала нажмите внешний 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

    
ответ дан Neha 07.03.2014 в 10:26
источник
  • Это не работает. Как получить доступ к $ event в рамках решения? –  HP. 08.03.2014 в 05:05
  • @HP. Я обновил ан. см., если его помощь. –  Neha 08.03.2014 в 08:48
  • Я щелкнул Inner, и он предупредил как Inner a, так и внешний, поэтому не выполнил требования –  HP. 08.03.2014 в 09:18
  • @HP Я обновил ответ, надеюсь, эта помощь! –  Neha 10.03.2014 в 04:58
  • Этот «взлом» работает, но он не идеален, поскольку у меня может быть внутренний1 до inner1000. Таким образом, решение должно быть достаточно общим, чтобы обрабатывать тонны разных DOM и состояний в других DOM с их собственными состояниями. –  HP. 10.03.2014 в 09:18
0

Проблема заключается не в вашем 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>
    
ответ дан himangshuj 07.03.2014 в 07:34
источник
  • См. мое обновление 1. Я знаю об изменении HTML, чтобы исправить это, но это не моя область. –  HP. 07.03.2014 в 10:09