Может ли родительское состояние UI-Router получить доступ к своим дочерним элементам? - PullRequest
0 голосов
/ 23 ноября 2018

Я использую AngularJS UI-Router для управления маршрутами для моего веб-приложения.

У меня есть два состояния: parent_state и child_state, расположенные, как показано ниже.

$stateProvider
.state('parent_state', {
    abstract: true,
    views: {
        '@' : {
            templateUrl: 'http://example.com/parent.html',
            controller: 'ParentCtrl'
        }
    }
})
.state('child_state', {
    parent: 'parent_state',
    url: '/child',
    params: {
      myArg: {value: null}
    },
    views: {
      'mainarea@parent_state': {
          templateUrl: 'http://example.com/child.html',
          controller: 'ChildCtrl'
        }
    }
})

Из ChildCtrl я могу получить доступ к myArg следующим образом:

app.controller("ChildCtrl", function($stateParams) {
    console.log('myArg = ', $stateParams.myArg);
});

Могу ли я получить доступ к myArg и отобразить его на html-странице parent.html?Если так, как это можно сделать?Я вижу, что контроллер ParentCtrl для абстрактного состояния даже никогда не вызывается.

Этот вопрос касается связанной темы.Но он не показывает, как отобразить параметр для дочернего состояния в шаблоне родительского состояния.

Ответы [ 3 ]

0 голосов
/ 27 ноября 2018

Могу ли я получить доступ к myArg и отобразить его на html-странице parent.html ?

Это противПринцип работы UI-Router .Родительские параметры можно употреблять детям, но не наоборот.Как родительский вид узнает об изменениях БЕЗ повторной инициализации контроллера?Вам нужно что-то вроде просмотра.

Истинный способ - использовать Множественные Именованные Представления .Посмотрите на этот рабочий plunkr .

0 голосов
/ 27 ноября 2018

Да, это возможно.

  1. Использование $ stateChangeSuccess :

Вы можете использовать $ stateChangeSuccess для достиженияthis.

Например:

.state('main.parent', {
  url: '/parent',
  controller: 'ParentController',
  controllerAs: 'vm',
  templateUrl: 'app/parent.html',
  data: {
    title: 'Parent'
  }
})
.state('main.parent.child', {
  url: '/child',
  controller: 'ChildController',
  controllerAs: 'vm',
  templateUrl: 'app/child.html'
})

И в runblock вызовите его следующим образом:

$rootScope.$on('$stateChangeSuccess', function (event, toState, fromState) {
  var current = $state.$current;
  if (current.data.hasOwnProperty('title')) {
    $rootScope.title = current.data.title;
  } else if(current.parent && current.parent.data.hasOwnProperty('title')) {
    $rootScope.title = current.parent.data.title;
  } else {
    $rootScope.title = null;
  }
});

Затем вы можете получить доступ к $ rootScope.title от дочернего элемента.контроллер, так как он доступен во всем мире.

Использование Фабрика или Сервис :

Записывая сеттеры и геттеры, вы можете передавать данные между контроллерами.Таким образом, вы можете установить данные из дочернего контроллера и получить данные из родительского контроллера.

'use strict';
(function () {
    var storeService = function () {
        //Getters and Setters to keep the values in session
        var headInfo = [];
        return {
            setData: function (key, data) {
                headInfo[key] = data;
            },
            getData: function (key) {
                return headInfo[key];
            }
        };
    };
    angular.module('MyApp')
        .factory('StoreService', storeService);
})(angular);

Установить данные из дочернего контроллера

StoreService.setData('title', $scope.title)

Получить данные

StoreService.getData('title');

Использование событий $ emit, $ on :

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

0 голосов
/ 26 ноября 2018

Первое, что приходит мне в голову, - это использовать события для уведомления родителя после смены дочернего параметра.Смотрите следующее (вы даже можете запустить его здесь).

Дочерний после рендеринга генерирует событие для родителя с измененным значением параметра.Родитель захватывает и отображает его в своем собственном шаблоне.

angular.module('myApp', ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
  $stateProvider
  .state('parent_state', {
    abstract: true,
    template: "<h1>Parent! Value from child: {{ paramFromChild }}</h1><div ui-view></div>",
    controller: function ($scope) {
      $scope.$on('childLoaded', function (e, param) {
        $scope.paramFromChild = param;
      });
    }
  })
  .state('child_state', {
    parent: 'parent_state',
    url: '/child',
    params: {
        myArg: {value: null}
    },
    template: '<h2>Child! Value: {{ param }}</h2>',
    controller: function($stateParams, $scope){ 
      $scope.param = $stateParams.myArg;
      $scope.$emit('childLoaded', $stateParams.myArg);
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.20/angular-ui-router.js"></script>

<div ng-app="myApp">
  <a ui-sref="child_state({myArg: 'first'})">First link</a>
  <a ui-sref="child_state({myArg: 'second'})">First second</a>
  <div ui-view></div>
</div>
...