2

Я все еще изучаю AngularJS, и у меня есть несколько концептуальных вопросов: что является лучшим способом подключить две смежные изолированные области в AngularJS? Под «смежными» областями я подразумеваю на одном уровне иерархически. Рассмотрим следующую структуру страницы:Как подключить смежные изолированные области в AngularJS

<div id="1" data-ng-app="angularApp"> 

    <div id="1A" data-ng-controller="colorCtrl as colorVm"> 
     <select data-ng-model="colorList" data-ng-options="color as color.name for color in colorVm.colors"> 
      <option>{{ color.name }}</option> 
     </select> 
    </div> 

    <div id="1B" data-ng-controller="secondCtrl as secondVm"> 
     <light-color /> 
    </div> 

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm"> 
     <light-color /> 
    </div> 

</div> 

«легкого цвета» директивы в ДИВ # 1B и ДИВ # 1С должна быть в состоянии получить доступ к информации из выпадающего меню в DIV # 1A. Каков наилучший способ сделать это без назначения 'colorCtrl' для div # 1 и расширения его возможностей? Любые мысли были бы оценены.

+0

иногда вам не нужно получать доступ к информации, но получать уведомление при изменении информации. В этом случае вы можете использовать $ scope. $ Emit() и $ scope. $ On() [подробнее здесь] (https://docs.angularjs.org/api/ng/type/$rootScope.Scope) –

ответ

0

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

<div id="1" data-ng-app="angularApp"> 

    <div id="1A" data-ng-controller="colorCtrl as colorVm"> 
     <select data-ng-model="colorVm.colorHelper.colorPick" data-ng-options="color as color.name for color in colorVm.colors"> 
      <option>{{ color.name }}</option> 
     </select> 
    </div> 

    <div id="1B" data-ng-controller="secondCtrl as secondVm"> 
     <light-color light-color-choice="{{ secondVm.colorHelper.colorPick.name }}" /> 
    </div> 

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm"> 
     <light-color light-color-choice="{{ thirdVm.colorHelper.colorPick.name }}" /> 
    </div> 

</div> 

И есть услуга (colorHelper.service.js), который выглядит следующим образом:

angular 
    .module('angularApp') 
    .service('colorHelper', function() { 

     var self = this; 

     self.colorPick; 

    return self; 
}); 

службы «colorHelper» подается в аргументы каждого контроллеров. Каждый контроллер затем имеет новое свойство, которое установлено равным службе colorHelper для этого контроллера, т.е.

var vm = this; 
vm.colorHelper = colorHelper; 

Таким образом, каждый контроллер имеет возможность получить доступ к colorVm.colorHelper.colorPick нг-модель при помощи свойства colorHelper.colorPick.name.

+0

Это, по сути, подробная версия решения, предложенного SteamDev. –

2

Вы можете ввести общую фабрику в каждый из контроллеров в качестве способа обмена данными между тремя разделами.

function colorCtrl($scope, ..., colorFactory){ 
    // use colorFactory for modifying/storing color data 
} 

function secondCtrl($scope, ..., colorFactory){ 
    // use colorFactory for modifying/storing color data 
} 

function thirdCtrl($scope, ..., colorFactory){ 
    // use colorFactory for modifying/storing color data 
} 
+0

Я действительно как простота этого ответа, но соглашения об именовании NG действительно ужасны ... Фабрика для чего-то, что реализуется как модель одноточечного типа/хранилище данных. О чем думали разработчики NG? – jusopi

0

Вы можете использовать scope events.

<div id="1A" data-ng-controller="colorCtrl as colorVm"> 
    <select ng-change="colorVm.colorChanged(selectedColor)" data-ng-model="selectedColor" data-ng-options="color as color.name for color in colorVm.colors"> 
     <option>{{ color.name }}</option> 
    </select> 
</div> 

, когда пользователь выбирает цвет из меню выбора colorVm.colorChanged() будет вызываться со значением модели selectedColor. Тогда в colorCtrl:

function ColorCtrl($scope, $rootScope) { 
    this.colors = [...]; 
    this.colorChanged = function(selectedColor) { 
     $rootScope.$broadcast('colorChanged', selectedColor); 
    } 
} 

затем в secondCtrl вы можете сделать:

function SecondCtrl($scope) { 
    $scope.$on('colorChanged', function(event, color) { 
     console.log(color + ' has been selected'); 
    }); 
} 

вы также можете слушать области видимости событий в директиве link функции:

... 
link: function(scope) { 
    scope.$on('colorChanged', function(event, color) { 
     console.log(color + ' has been selected'); 
    }); 
} 
... 
+0

Мне нравится эта идея, но как бы вы абстрагировали функцию colorChanged с директивой светового цвета? Другими словами, запускать директиву светового цвета для выполнения, где у вас есть строка «console.log (color + ...»)? –

+0

функция обратного вызова $ scope. $ On вызывается каждый раз, когда угловое событие является '$ emit'ed или' $ broadcast'ed. подобно вызову события JS 'elem.addEventListener ('click', function() {})' –

0

Инициализировать объект на родительском пространстве. Попросите директиву ng-model подключиться к свойству этого объекта. Этот объект будет унаследован дочерними областями.

Команда AngularJS рекомендует выполнять инициализацию в контроллере. В этом примере я использую ng-init для иллюстрации. В производственном коде инициализации лучше всего выполнять в контроллере.

<div id="1" data-ng-app="angularApp"> 
    <div ng-init="x='{}'"></div> 
    <div id="1A" data-ng-controller="colorCtrl as colorVm"> 
     <select ng-model="x.colorList" 
       ng-options="color as color.name for color in colorVm.colors"> 
     </select> 
    </div> 

    <div id="1B" data-ng-controller="secondCtrl as secondVm"> 
     <light-color color='x.colorList'/> 
    </div> 

    <div id="1C" data-ng-controller="thirdCtrl as thirdVm"> 
     <light-color color='x.colorList'/> 
    </div> 

</div> 

В директиве с изолята рамки, установить атрибут к имени переменной, и объявить, что атрибут с 2-полосная связывания.

angular.module('angularApp').directive('lightColor', function() { 
    return { 
     restrict: 'E', 
     scope: {color: '='}, 
     template: '<p> lightColor color.name={{color.name}}</p>' 
    } 
}) 

Помните, что правило с ng-model всегда использует точку.

DEMO on JSFiddle

+0

angular [docs] (https://docs.angularjs.org/api/ng/directive/ngInit) отказать в использовании ngInit для таких случаев. –

+0

@ Аррустамян Спасибо. Я обновил ответ, чтобы включить этот совет. – georgeawg