Дочерний маршрут продолжает запускать родительский при использовании ui-sref-active-eq (angular-ui-router)

#angularjs #angular-ui-router

#angularjs #angular-ui-router

Вопрос:

У меня есть маршрут, в angular-ui-router котором есть дочерние маршруты; Я хочу, чтобы ссылки на эти дочерние маршруты были видны только на родительском маршруте. Они присутствуют в меню, которое видно для всего приложения, но каждая ссылка зависит от параметра url в родительском для работы, поэтому крайне важно, чтобы они не были интерактивными, когда этот параметр не существует.

Итак, настройка такая;

 .state('route1', {
   url: '/route1/:id',
   views: { 'main@': { template: '<route1-component></route1-component>' } }
})
.state('route1.child1', {
   url: '/child1',
   views: { 'main@': { template: '<route1-child1-component></route1-child1-component>' } }
})
  

Я получил возможность скрывать их для работы, используя ui-sref в сочетании с ui-sref-active-eq , используя этот макет…

 <div ui-sref="route1" ui-sref-active-eq="visible" hidden>
   <a ui-sref="route1.child1" ui-sref-opts="{ location: true, inherit: true, relative: true }">CHILD 1</a>
</div>
  

Сначала это работает нормально; Ссылка видна только тогда, когда мы находимся на route1 маршруте. URL, который он показывает #/route1/1/child1 , включает :id параметр текущего URL.

Но когда я нажимаю на ссылку, URL-адрес мигает как #/route1/1/child1 на короткое мгновение, но затем route1 снова отображается.

Если я удалю ui-sref-active-eq часть, она правильно перенаправит на дочерний маршрут. Но тогда у меня проблема с тем, что он не скрыт в противном случае.

Есть ли что-нибудь, что можно сделать?

Пожалуйста, обратите внимание, я использую исключительно компоненты angular 1.5 . Я вообще не использую обычные контроллеры или директивы. Это все 100% компоненты.

Это не совсем идеально, но это пример того, как все устроено, и я попытался прояснить, как они должны функционировать. Кажется, я не могу получить $state внутри директивы для наблюдения за изменениями. https://plnkr.co/edit/rxjVbckhwxdYPRAX4uiU?p=preview

Комментарии:

1. в худшем случае создайте свою собственную директиву, которая использует $state.includes() или другие утилиты, встроенные в $state

2. Я не уверен, как вы будете прослушивать изменение состояния там. Похоже, это не работает, когда я подключаюсь $stateChangeStart к $rootScope чему-либо, кроме run функции конфигурации модуля.

3. также может быть введен $state в директиву. создайте демонстрацию, которая повторяет проблему

4. Да, это не работает. .directive('uiSrefVisible', function () { return { restrict: 'A', controller: function($rootScope, $state, $stateParams) { $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){ console.log('test'); }) }, link: function (scope, element, attributes) { } } })

5. Это просто не работает. Он никогда не запускается. Единственное место, где он запускается, находится внутри начальной run функции.

Ответ №1:

следующее добавляет контроллер к вашему компоненту sidenav и использует $stateChangeSuccess событие и $state.includes() для обновления логического значения, переданного ng-show

   .component('sidenav', {
    controller: function ($rootScope,$state) {
      var vm = this;
      vm.isRoute1=$state.includes('route1');
      $rootScope.$on('$stateChangeSuccess', function(evt, to, from){
          vm.isRoute1=$state.includes('route1');
      });            
   },
    template: `
        <div  ng-show="$ctrl.isRoute1">
          <a ui-sref="route1.child1" ui-sref-opts="{ location: true, inherit: true, relative: true }">
            ROUTE 1 CHILD 1 LINK
          </a>
        </div>`

  })
  

Я думаю, что это то поведение, которое вы хотите… однако не уверен на 100%

DEMO

Комментарии:

1. Вау! Это не совсем поведение, но оно демонстрирует принцип. Я думаю, что я могу достаточно легко абстрагировать это от чего-то более масштабируемого. Спасибо за работу со мной. Честно говоря, это первый раз, когда я написал какой-либо angular на чистом javascript, так что это было довольно запутанно, начиная с typescript.

2. настоятельно рекомендуем избегать именования пользовательских директив с префиксами, которые очень близки к существующим модулям, иначе позже вы не поймете, что они не являются частью этого модуля

3. Это было больше просто для примера. Хотя я, похоже, не могу повторить это в Typescript … это очень своеобразно. Кажется, я просто не могу заставить $rootScope.$on его сработать. Это действительно странно…

4. я начал делать это как директиву, и если вам нужна масштабируемость, то директива может быть лучшим подходом… затем может передавать привязки через атрибуты

5. Однако это не имеет особого смысла. Он отлично работает на контроллере компонентов в вашем примере, но когда я помещаю его в машинопись, $rootScope он есть. Я могу распечатать его. Но $on никогда не срабатывает. Это просто так caddywhompus.