2015-06-22 6 views
2

Каков предпочтительный способ соединения/объединения двух директив вместе? У меня есть контроллер с двумя директивами, первая директива - это элемент выбора, после выбора опции вторая директива должна обрабатывать выбранное значение элемента.AngularJS - связывание/связывание двух директив вместе

App код:

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

app.controller('MainCtrl', function() { 
    var sharedData = { selectedId: '' }; 

    var vm = this; 

    vm.sharedData = sharedData; 
}); 

app.directive('directiveA', ['$compile', function($compile) { 
    return { 
    restrict: 'E', 
    scope: { 
     selectedId: '=' 
    }, 
    template: '<select data-ng-model="vm.sharedData.selectedId" data-ng-options="currentSelect.Id as currentSelect.Name for currentSelect in vm.sharedData.availableSelects track by currentSelect.Id"><option value="">Select option</option></select><p>Directive A, selected ID: {{vm.sharedData.selectedId}}</p>', 
    bindToController: true, 
    controllerAs: 'vm', 
    controller: function() { 
     vm = this; 

     vm.sharedData = { 
     availableSelects: [ 
      {Id:1, Name: 'Option 1'}, 
      {Id:2, Name: 'Option 2'}, 
      {Id:3, Name: 'Option 3'}, 
      {Id:4, Name: 'Option 4'} 
     ] 
     } 
     vm.logMessage = logMessage; 

     function logMessage(selectedId) { 
     console.log('directiveA: ' + selectedId); 
     } 
    }, 
    link: function($scope, elem, attr, ctrl) { 
     attr.$observe('selectedId', function(selectedId) { 
     ctrl.logMessage(selectedId); 
     }); 
    } 
    }; 
}]); 

app.directive('directiveB', ['$compile', function($compile) { 
    return { 
    restrict: 'E', 
    scope: { 
     selectedId: '=' 
    }, 
    template: '<p>Directive B, selected ID: {{vm.sharedData.selectedId}}</p>', 
    bindToController: true, 
    controllerAs: 'vm', 
    controller: function() { 
     vm = this; 

     vm.logMessage = logMessage; 

     function logMessage(selectedId) { 
     console.log('directiveB: ' + selectedId); 
     } 
    }, 
    link: function($scope, elem, attr, ctrl) { 
     attr.$observe('selectedId', function(selectedId) { 
     ctrl.logMessage(selectedId); 
     }); 
    } 
    }; 
}]); 

HTML код:

<!DOCTYPE html> 
<html data-ng-app="plunker" data-ng-strict-di> 
    <head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script>document.write('<base href="' + document.location + '" />');</script> 
    <link href="style.css" rel="stylesheet" /> 
    <script data-semver="1.4.1" src="https://code.angularjs.org/1.4.1/angular.js" data-require="[email protected]"></script> 
    <script src="app.js"></script> 
    </head> 

    <body ng-controller="MainCtrl as vm"> 
    <p>MainCtrl, selected ID: {{vm.sharedData.selectedId}}</p> 
    <directive-a data-selected-id="vm.sharedData.selectedId"></directive-a> 
    <directive-b data-selected-id="vm.sharedData.selectedId"></directive-b> 
    </body> 

</html> 

Вот пример Plunker:

http://plnkr.co/edit/KVMGb8uAjUwD9eOsv72z?p=preview

Что я делаю неправильно?

С наилучшими пожеланиями,

+0

У вас есть две директивы, для которых требуется изолированный объект на том же элементе, который не разрешен. Это дублирующий вопрос. http://stackoverflow.com/questions/20470662/angularjs-two-directives-on-one-element –

+0

ЕСЛИ я правильно понял ваше требование, думаю, вам нужно использовать require для ссылок между двумя контроллерами, http: // stackoverflow .com/questions/30673459/using-require-in-directive-to-require-a-parent-controller/30673703 # 30673703 –

+0

Хм, http://stackoverflow.com/questions/20470662/angularjs-two-directives- on-one-element имеет две директивы для одного элемента (), но здесь у меня есть две независимые директивы для одной переменной. – Sassa

ответ

1

Ключевой вопрос вращается вокруг использования выделенных областей:

scope: { 
    selectedId: '=' 
}, 

С controllerAs связывания:

controllerAs: 'vm', 

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

<directive-a data-selected-id="vm.sharedData.selectedId"></directive-a> 

Вы фактически получить доступ к директивной-модели представления, а не вид модель MainCtrl. ПОСЛЕ того, что вы устанавливаете директиву как имеющую область выделения ... которая является новой областью, изолированной от MainCtrl.

Что вам нужно сделать, это более по следующим направлениям:

http://plnkr.co/edit/wU709MPdqn5m2fF8gX23?p=preview


EDIT

TLDR: Я рекомендовал бы уникальный вид модели псевдонимами (controllerAs) при работе с изолированными областями, чтобы правильно отразить тот факт, что они не являются одной и той же моделью просмотра.

+0

Просто добавьте: В основном, что я сделал, в MainCtrl vm хранится выбранный идентификатор, который затем двусторонний привязан к обоим дочерним директивам с помощью модели представления MainCtrl (mainVm). Затем это свойство привязано к дочерним директивам соответствующих моделей представлений: aVm и bVm. Когда они изменяют или получают доступ к этим свойствам, они фактически будут обращаться к родительскому свойству mainVm.selectedId из-за двусторонней привязки в объявлениях изоляции. –

+0

Спасибо, это то, что мне нужно! Я забываю о разных именах для модели «controllerAs». – Sassa

+0

Рад, что я мог бы помочь :) Понимание понимания всегда является большой частью углового, и controllerAs (наряду с bindToController) имеет большое значение, помогая устранить неоднозначность того, какие объекты/переменные связаны. Поэтому здорово видеть, что вы пытаетесь использовать этот шаблон. –

Смежные вопросы