Подтвердить что ты не робот

AngularJS: ng-include и ng-controller

У меня есть приложение, которое я создаю с помощью angular, у меня есть около 8-10 просмотров для создания. Все представления имеют общий нижний колонтитул, основанный на представлении и наборе бизнес-правил, которые мне нужно условно показать/скрыть часть содержимого на нижнем колонтитуле.

Итак. У меня есть контроллеры для каждого вида, а затем один для нижнего колонтитула. Я включаю общий макет нижнего колонтитула с помощью ng-include, где html, который я включаю, ссылается на контроллер нижнего колонтитула в ng-контроллере.

Index.html

<body ng-controller="MainCtrl as vm">
    <p>Message from Main Controller '{{vm.mainMessage}}'</p>
    <div ng-include="'commonFooter.html'"></div>
</body>

commonFooter.html

<div ng-controller="FooterCtrl as vm">
    <p>Message from Footer Controller '{{vm.message}}'</p>
    <p ng-show="vm.showSomthing">Conditional footer Content</p>
</div>

Я хочу, чтобы каждый контроллер просмотров определял состояние нижнего колонтитула и скрывал ли конкретный контент или нет. (shouldDisplaySomthingInFooter ниже)

app.controller('MainCtrl', function($scope) {
  var vm = this;
  vm.mainMessage= 'HEELO';
  vm.shouldDisplaySomthingInFooter = true;
  window.console.log('Main scope id: ' + $scope.$id);
});

Затем я предположил, что в FooterController вернется в родительский контроллер и вытащит конкретные настройки для включения/отключения содержимого на основе бизнес-правил.

app.controller('FooterCtrl', function($scope) {
    var vm = this;
  vm.message = 'vm footer';

  window.console.log('Footer scope id: ' + $scope.$id);
  window.console.log('Footer parent scope id: ' + $scope.$parent.$id);
  window.console.log('Footer grandparent scope id: ' + $scope.$parent.$parent.$id);
  window.console.log('Footer grandparent scope name: ' + $scope.$parent.$parent.mainMessage);
  window.console.log('Footer grandparent scope condition: ' + $scope.$parent.$parent.shouldDisplaySomthingInFooter);

  vm.showSomthing = false; //how to pull from parent scope to bind the ng-show to a value set in the parent from within a ng-include?
});

У меня есть этот пример здесь: http://plnkr.co/edit/ucI5Cu4jjPgZNUitY2w0?p=preview

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

Я вижу, что области привязаны к уровню grandparent, проверяя scopeid, я считаю, что это связано с тем, что ng-include добавляет дополнительный уровень видимости под областями представления. outout from console in attached example

Дополнительные баллы: если мне не нужно использовать объект $scope и можете придерживаться способа var vm = this; сделать это, что было бы предпочтительнее. Но нищие не могут выбирать:)

app.controller('MainCtrl', function($scope) {
  var vm = this;

Спасибо вам заблаговременно.

4b9b3361

Ответ 1

Если вы используете внешний контроллер в качестве vm и ваш внутренний контроллер как foo, вы можете легко их отделить и обратиться к vm внутри внутреннего контроллера.

Демо

HTML

<body ng-controller="MainCtrl as vm">
    <p>Message from Main Controller '{{vm.mainMessage}}'</p>
    <div ng-include="'commonFooter.html'"></div>
</body>

CommonFooter.html

<div ng-controller="FooterCtrl as footer">
    <p>Message from Footer Controller '{{footer.message}}'</p>
    <p ng-show="vm.shouldDisplaySomethingInFooter">Conditional footer Content</p>
</div>

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function() {
    var self = this;
    self.mainMessage = 'Hello world';
    self.shouldDisplaySomethingInFooter = true;
});

app.controller('FooterCtrl', function() {
    var self = this;
    self.message = 'vm footer';
});

Примечание. Для ясности я переименовал ваш var vm = this в var self = this и уменьшил путаницу между вашими представлениями и вашими контроллерами.

Ожидаемый результат:

output showing the conditionally hidden\shown items

Ответ 2

Вы неправильно поняли, что используется как синтаксис контроллера (см. документацию). Это всего лишь способ разоблачить конкретный контроллер в вашей локальной области, чтобы вы могли получить доступ к его свойствам из шаблона. Когда вы используете someController as vm в обоих шаблонах родителя и нижнего колонтитула, вы каким-то образом не создаете соединение между контроллерами или чем-либо подобным. Вы просто устанавливаете свойство vm в области нижнего колонтитула, поэтому, когда вы используете его в шаблоне нижнего колонтитула, вы получаете доступ к контроллеру нижнего колонтитула (и вы заблокировали свой путь к родительскому контроллеру).

Для того, что вы пытаетесь сделать, вам вообще не нужен контроллер как синтаксис. Просто разместите свои данные на $scope, и пусть иерархия области сделает для вас все остальное.

В вашем родительском контроллере:

$scope.features.rock = true;
$scope.features.roll = false;

В шаблоне нижнего колонтитула

<p ng-show="features.rock">...</p>
<p ng-show="features.roll">...</p>

Теперь вы можете также видеть и изменять features с других контроллеров (поскольку их области видимости являются потомками области родительского контроллера).

Ответ 3

Я поиграл с вашим плунжером, но также изменил var vm = this; на $scope, поэтому я не могу выполнить дополнительные очки: -)

Я бы настоятельно рекомендовал использовать $scope.$parent именно по той причине, что вы показываете. Различные директивы, такие как ng-include, ng-show и т.д., Генерируют свои собственные области.

У вас нет контроля, если кто-то в будущем изменит ваш html и добавит области, умышленно или иначе.

Я рекомендую использовать функции, которые находятся на вашем MainCtrl и доступ к ним через наследование областей.

Plunker

$scope.getShouldShow = function() {
    return $scope.shouldDisplaySomthingInFooter;
  };
  $scope.setShouldShow = function(val) {
    $scope.shouldDisplaySomthingInFooter = val;
  };

  $scope.getMainMessage = function () {
    return $scope.mainMessage;
  }

И называя их:

<p ng-show="getShouldShow();">Conditional footer Content</p>

и

  window.console.log('Footer grandparent scope name: ' + $scope.getMainMessage());
  window.console.log('Footer grandparent scope condition: ' + $scope.getShouldShow());