ผู้ควบคุม AngularJS หนึ่งคนสามารถเรียกอีกคนหนึ่งได้หรือไม่


581

เป็นไปได้ไหมที่จะมีคอนโทรลเลอร์หนึ่งอันใช้อีกคอนโทรลเลอร์หนึ่ง?

ตัวอย่างเช่น:

เอกสาร HTML นี้จะพิมพ์ข้อความที่จัดส่งโดยMessageCtrlคอนโทรลเลอร์ในmessageCtrl.jsไฟล์

<html xmlns:ng="http://angularjs.org/">
<head>
    <meta charset="utf-8" />
    <title>Inter Controller Communication</title>
</head>
<body>
    <div ng:controller="MessageCtrl">
        <p>{{message}}</p>
    </div>

    <!-- Angular Scripts -->
    <script src="http://code.angularjs.org/angular-0.9.19.js" ng:autobind></script>
    <script src="js/messageCtrl.js" type="text/javascript"></script>
</body>
</html>

ไฟล์คอนโทรลเลอร์มีรหัสต่อไปนี้:

function MessageCtrl()
{
    this.message = function() { 
        return "The current date is: " + new Date().toString(); 
    };
}

ซึ่งเพียงพิมพ์วันที่ปัจจุบัน

ถ้าฉันจะเพิ่มตัวควบคุมอื่นDateCtrlซึ่งส่งวันที่ในรูปแบบเฉพาะกลับไปMessageCtrlหนึ่งจะไปทำเช่นนี้ได้อย่างไร กรอบ DI น่าจะเกี่ยวข้องXmlHttpRequestsและเข้าถึงบริการ


4
เธรดกลุ่ม google นี้, groups.google.com/d/topic/angular/m_mn-8gnNt4/discussionกล่าวถึง 5 วิธีที่ผู้ควบคุมสามารถพูดคุยกันได้
Mark Rajcok

มีคำตอบที่ดีอยู่แล้วดังนั้นฉันอยากจะชี้ให้เห็นว่าสำหรับกรณีการใช้งานเฉพาะที่กล่าวถึงบางทีตัวกรอง AngularJS อาจเป็นทางออกที่ดีกว่า เพียงแค่คิดว่าฉันต้องการพูดถึงมัน :)
โจ Dyndale

คำตอบ:


705

มีหลายวิธีในการสื่อสารระหว่างคอนโทรลเลอร์

สิ่งที่ดีที่สุดอาจเป็นการแบ่งปันบริการ:

function FirstController(someDataService) 
{
  // use the data service, bind to template...
  // or call methods on someDataService to send a request to server
}

function SecondController(someDataService) 
{
  // has a reference to the same instance of the service
  // so if the service updates state for example, this controller knows about it
}

อีกวิธีหนึ่งคือปล่อยเหตุการณ์ตามขอบเขต:

function FirstController($scope) 
{
  $scope.$on('someEvent', function(event, args) {});
  // another controller or even directive
}

function SecondController($scope) 
{
  $scope.$emit('someEvent', args);
}

ในทั้งสองกรณีคุณสามารถสื่อสารกับคำสั่งใด ๆ เช่นกัน


4
เฮียตัวอย่างแรกจะต้องให้หน้าเว็บต้องระวังบริการทั้งหมดในสแต็ก ซึ่งรู้สึกเหมือนมีกลิ่นเหม็น (?) เช่นเดียวกับที่สองหน้าเว็บจะไม่ต้องให้อาร์กิวเมนต์ $ scope หรือไม่
BanksySan

54
อะไร? ทำไม? คอนโทรลเลอร์ทั้งหมดถูกฉีดโดย DI ของ Angular
Vojta

7
@JoshNoe ใน 1 / คุณมีสองตัวควบคุม (หรือมากกว่า) และพวกเขาทั้งสองได้รับบริการที่เหมือนกัน / ที่ใช้ร่วมกัน จากนั้นคุณมีวิธีสื่อสารหลายวิธีบางวิธีที่คุณพูดถึง ฉันจะตัดสินใจตามกรณีการใช้งานเฉพาะของคุณ คุณสามารถใส่ตรรกะ / สถานะที่ใช้ร่วมกันลงในบริการและผู้ควบคุมทั้งสองจะมอบสิทธิ์ให้กับบริการนั้นหรือแม้แต่ส่งออกบริการไปยังเทมเพลต แน่นอนบริการนี้ยังสามารถยิงเหตุการณ์ได้อีกด้วย ...
Vojta

137
มาถึงช่วงดึก: พวกคุณรู้หรือไม่ว่าคุณกำลังโต้เถียงกับ THE Vojta จาก Google ที่ทำงานกับ AngularJS ใช่มั้ย :)
Suman

16
ฉันไม่เห็นชัดเจนว่าใน HTML ของฉันตัวควบคุมการเปล่งเหตุการณ์จะต้องเป็นโหนดย่อยของตัวควบคุมการฟังเพื่อให้ทำงานได้
djangonaut

122

ดูซอนี้: http://jsfiddle.net/simpulton/XqDxG/

ดูวิดีโอต่อไปนี้ด้วย: การสื่อสารระหว่างตัวควบคุม

Html:

<div ng-controller="ControllerZero">
  <input ng-model="message" >
  <button ng-click="handleClick(message);">LOG</button>
</div>

<div ng-controller="ControllerOne">
  <input ng-model="message" >
</div>

<div ng-controller="ControllerTwo">
  <input ng-model="message" >
</div>

javascript:

var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
  var sharedService = {};

  sharedService.message = '';

  sharedService.prepForBroadcast = function(msg) {
    this.message = msg;
    this.broadcastItem();
  };

  sharedService.broadcastItem = function() {
    $rootScope.$broadcast('handleBroadcast');
  };

  return sharedService;
});

function ControllerZero($scope, sharedService) {
  $scope.handleClick = function(msg) {
    sharedService.prepForBroadcast(msg);
  };

  $scope.$on('handleBroadcast', function() {
    $scope.message = sharedService.message;
  });        
}

function ControllerOne($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'ONE: ' + sharedService.message;
  });        
}

function ControllerTwo($scope, sharedService) {
  $scope.$on('handleBroadcast', function() {
    $scope.message = 'TWO: ' + sharedService.message;
  });
}

ControllerZero.$inject = ['$scope', 'mySharedService'];        

ControllerOne.$inject = ['$scope', 'mySharedService'];

ControllerTwo.$inject = ['$scope', 'mySharedService'];

12
ซอและวิดีโอด้านบนใช้บริการร่วมกัน นี่คือซอที่ใช้ $ scope $ emit: jsfiddle.net/VxafF
Mark Rajcok

1
@ การออกแบบ: ฉันชอบที่จะอ่านตัวอย่างที่กระชับและมีความหมายเดียวกันสำหรับคำสั่ง (ขอบคุณสำหรับคำตอบนี้ด้วย!)
sscarduzio

คำตอบที่ดีฉันใช้ myModule.service ('mySharedService', ฟังก์ชั่น ($ rootScope) {}) แทน myModule.factory แต่ใช้งานได้น้อยกว่า!
TacoEater

ยอดเยี่ยม แม้ว่าฉันมีคำถาม: ทำไมคุณเพิ่มตัวจัดการภายใน ControllerZero? $ scope $ on ('handleBroadcast', function () {$ scope.message = sharedService.message;});
ZooZ

วิดีโอที่ให้มานั้นยอดเยี่ยมจริงๆ! ฉันดูเหมือนว่านี่คือสิ่งที่ฉันต้องการเพื่อสอบถามสถานะของตัวควบคุมอื่นจากตัวควบคุมอื่น อย่างไรก็ตามสิ่งนี้ไม่ทำงานโดยใช้ฟังก์ชั่น "เรียกใช้" มันทำงานโดยใช้การกระทำ "ทริกเกอร์" อย่างมีประสิทธิภาพหากผู้ควบคุมดำเนินการและมีสถานะใหม่จากนั้นก็จะต้องออกอากาศรัฐและขึ้นอยู่กับผู้ควบคุมอื่น ๆ ที่จะรับฟังการออกอากาศนั้นและตอบสนองตามนั้น หรือดีกว่าดำเนินการในบริการที่ใช้ร่วมกันแล้วเผยแพร่สถานะ โปรดบอกฉันว่าความเข้าใจของฉันถูกต้องหรือไม่
tarekahf

53

ถ้าคุณต้องการเรียกตัวควบคุมหนึ่งไปยังอีกตัวหนึ่งมีสี่วิธีให้เลือก

  1. $ rootScope. $ emit () และ $ rootScope. $ ออกอากาศ ()
  2. หากคอนโทรลเลอร์ตัวที่สองคือลูกคุณสามารถใช้การสื่อสารลูกแม่
  3. ใช้บริการ
  4. ชนิดของการแฮ็ค - ด้วยความช่วยเหลือของเชิงมุมองค์ประกอบ ()

1. $ rootScope. $ emit () และ $ rootScope. $ ออกอากาศ ()

คอนโทรลเลอร์และขอบเขตของมันสามารถถูกทำลายได้ แต่ $ rootScope ยังคงอยู่ในแอปพลิเคชันนั่นคือเหตุผลที่เรารับ $ rootScope เพราะ $ rootScope เป็นแหล่งกำเนิดของขอบเขตทั้งหมด

หากคุณทำการสื่อสารจากผู้ปกครองไปยังเด็กและแม้กระทั่งเด็กต้องการที่จะสื่อสารกับพี่น้องของคุณคุณสามารถใช้ $ ออกอากาศ

หากคุณทำการสื่อสารจากเด็กไปยังผู้ปกครองไม่มีพี่น้องที่ invovled คุณสามารถใช้ $ rootScope ได้ $ emit

HTML

<body ng-app="myApp">
    <div ng-controller="ParentCtrl" class="ng-scope">
      // ParentCtrl
      <div ng-controller="Sibling1" class="ng-scope">
        // Sibling first controller
      </div>
      <div ng-controller="Sibling2" class="ng-scope">
        // Sibling Second controller
        <div ng-controller="Child" class="ng-scope">
          // Child controller
        </div>
      </div>
    </div>
</body>

รหัส Angularjs

 var app =  angular.module('myApp',[]);//We will use it throughout the example 
    app.controller('Child', function($rootScope) {
      $rootScope.$emit('childEmit', 'Child calling parent');
      $rootScope.$broadcast('siblingAndParent');
    });

app.controller('Sibling1', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside Sibling one');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

app.controller('Sibling2', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside Sibling two');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

app.controller('ParentCtrl', function($rootScope) {
  $rootScope.$on('childEmit', function(event, data) {
    console.log(data + ' Inside parent controller');
  });
  $rootScope.$on('siblingAndParent', function(event, data) {
    console.log('broadcast from child in parent');
  });
});

ในโค้ดคอนโซลด้านบนของ $ emit 'childEmit' จะไม่เรียกภายในพี่น้องเด็กและมันจะโทรภายใน parent เท่านั้นโดยที่ $ broadcast ถูกเรียกภายในพี่น้องและผู้ปกครองด้วยนี่คือสถานที่ที่ประสิทธิภาพเข้าสู่การดำเนินการ $ emit คือ ดีกว่าถ้าคุณใช้การสื่อสารลูกกับผู้ปกครองเพราะข้ามการตรวจสอบสกปรกบางอย่าง

2. หากคอนโทรลเลอร์ตัวที่สองเป็นลูกคุณสามารถใช้การสื่อสารหลักได้

เป็นหนึ่งในวิธีที่ดีที่สุดหากคุณต้องการสื่อสารกับผู้ปกครองของเด็กที่เด็กต้องการสื่อสารกับผู้ปกครองทันทีมันไม่จำเป็นต้องมี $ broadcast หรือ $ emit ใด ๆ แต่ถ้าคุณต้องการสื่อสารจาก parent ถึง child คุณต้อง ใช้บริการอย่างใดอย่างหนึ่งหรือ $ ออกอากาศ

ตัวอย่างเช่น HTML: -

<div ng-controller="ParentCtrl">
 <div ng-controller="ChildCtrl">
 </div>
</div>

Angularjs

 app.controller('ParentCtrl', function($scope) {
   $scope.value='Its parent';
      });
  app.controller('ChildCtrl', function($scope) {
   console.log($scope.value);
  });

เมื่อใดก็ตามที่คุณใช้การสื่อสารลูกกับผู้ปกครอง Angularjs จะค้นหาตัวแปรภายในลูกถ้าไม่อยู่ข้างในก็จะเลือกดูค่าภายในตัวควบคุมหลัก

3. ใช้บริการ

AngularJS สนับสนุนแนวคิดของ"การแยกความกังวล"โดยใช้สถาปัตยกรรมบริการ บริการเป็นฟังก์ชั่นจาวาสคริปต์และมีความรับผิดชอบในการทำงานที่เฉพาะเจาะจงเท่านั้นซึ่งจะทำให้พวกเขาเป็นนิติบุคคลที่สามารถบำรุงรักษาและทดสอบได้บริการที่ใช้ในการฉีดโดยใช้การฉีดขึ้นอยู่กับ mecahnism ของ Angularjs

รหัส Angularjs:

app.service('communicate',function(){
  this.communicateValue='Hello';
});

app.controller('ParentCtrl',function(communicate){//Dependency Injection
  console.log(communicate.communicateValue+" Parent World");
});

app.controller('ChildCtrl',function(communicate){//Dependency Injection
  console.log(communicate.communicateValue+" Child World");
});

มันจะให้ผลลัพธ์ Hello Child World และ Hello Parent World ตามเอกสารเชิงมุมของการบริการSingletons - องค์ประกอบแต่ละขึ้นอยู่กับบริการที่ได้รับการอ้างอิงถึงตัวอย่างเดียวที่สร้างขึ้นโดยโรงงานบริการ

4.Kind of Hacking - ด้วยความช่วยเหลือของ angular.element ()

เมธอดนี้รับขอบเขต () จากองค์ประกอบโดย Id / unique class.angular.element () วิธีการคืนองค์ประกอบและขอบเขต () ให้ตัวแปร $ scope ของตัวแปรอื่นโดยใช้ตัวแปร $ scope ของตัวควบคุมหนึ่งภายในอื่นไม่ปฏิบัติที่ดี

HTML: -

<div id='parent' ng-controller='ParentCtrl'>{{varParent}}
 <span ng-click='getValueFromChild()'>Click to get ValueFormChild</span>
 <div id='child' ng-controller='childCtrl'>{{varChild}}
   <span ng-click='getValueFromParent()'>Click to get ValueFormParent </span>
 </div>
</div>

Angularjs: -

app.controller('ParentCtrl',function($scope){
 $scope.varParent="Hello Parent";
  $scope.getValueFromChild=function(){
  var childScope=angular.element('#child').scope();
  console.log(childScope.varChild);
  }
});

app.controller('ChildCtrl',function($scope){
 $scope.varChild="Hello Child";
  $scope.getValueFromParent=function(){
  var parentScope=angular.element('#parent').scope();
  console.log(parentScope.varParent);
  }
}); 

ในตัวควบคุมรหัสข้างต้นจะแสดงค่าของตัวเองใน Html และเมื่อคุณจะคลิกที่ข้อความคุณจะได้รับค่าในคอนโซลตามหากคุณคลิกที่ตัวควบคุมผู้ปกครองช่วงเบราว์เซอร์จะคอนโซลค่าของเด็กและ viceversa


52

นี่คือตัวอย่างหน้าเดียวของคอนโทรลเลอร์สองตัวที่แชร์ข้อมูลบริการ:

<!doctype html>
<html ng-app="project">
<head>
    <title>Angular: Service example</title>
    <script src="http://code.angularjs.org/angular-1.0.1.js"></script>
    <script>
var projectModule = angular.module('project',[]);

projectModule.factory('theService', function() {  
    return {
        thing : {
            x : 100
        }
    };
});

function FirstCtrl($scope, theService) {
    $scope.thing = theService.thing;
    $scope.name = "First Controller";
}

function SecondCtrl($scope, theService) {   
    $scope.someThing = theService.thing; 
    $scope.name = "Second Controller!";
}
    </script>
</head>
<body>  
    <div ng-controller="FirstCtrl">
        <h2>{{name}}</h2>
        <input ng-model="thing.x"/>         
    </div>

    <div ng-controller="SecondCtrl">
        <h2>{{name}}</h2>
        <input ng-model="someThing.x"/>             
    </div>
</body>
</html>

นอกจากนี้ที่นี่: https://gist.github.com/3595424


และหากtheServiceมีการอัปเดตการthing.xเปลี่ยนแปลงนั้นจะส่งไปที่ <input> โดยอัตโนมัติFirstCtrlและSecondCtrlใช่ไหม และยังสามารถเปลี่ยนthing.xได้โดยตรงผ่าน <input> ใด ๆ ของทั้งสอง (ขวา?)
KajMagnus

4
ใช่. บริการเชิงมุมทั้งหมดเป็นแอพพลิเคชั่นซิงเกิลตันซึ่งหมายความว่ามีเพียงอินสแตนซ์เดียวของบริการ การอ้างอิง: docs.angularjs.org/guide/dev_guide.services.creating_services
exclsr

ลิงก์ในความคิดเห็นก่อนหน้าของฉันคือ 404 ดังนั้นนี่คือคำแนะนำบริการวันนี้บริการบันทึกย่อคือ singletons: docs.angularjs.org/guide/services
exclsr

1
@exclsr ใช่! ขออภัยฉันพลาดไปก่อนหน้านี้
CodyBugstein

3
ตัวอย่างที่ดีที่สุดที่ฉันเคยเห็นบนเว็บจนถึงตอนนี้ ขอบคุณ
Sevenearths

33

หากคุณต้องการปล่อยและออกอากาศกิจกรรมเพื่อแบ่งปันข้อมูลหรือฟังก์ชั่นการโทรระหว่างคอนโทรลเลอร์โปรดดูที่ลิงก์นี้: และตรวจสอบคำตอบโดยzbynour(ตอบด้วยคะแนนโหวตสูงสุด) ฉันอ้างคำตอบของเขา !!!

หากขอบเขตของ firstCtrl เป็นพาเรนต์ของขอบเขต secondCtrl รหัสของคุณควรทำงานโดยแทนที่ $ emit ด้วย $ broadcast ใน firstCtrl:

function firstCtrl($scope){
    $scope.$broadcast('someEvent', [1,2,3]);
}

function secondCtrl($scope){
    $scope.$on('someEvent', function(event, mass) {console.log(mass)});
}

ในกรณีที่ไม่มีความสัมพันธ์ระหว่างแม่ลูกคุณสามารถฉีด $ rootScope ลงในคอนโทรลเลอร์และถ่ายทอดเหตุการณ์ไปยังขอบเขตเด็กทั้งหมด (เช่น secondCtrl)

function firstCtrl($rootScope){
    $rootScope.$broadcast('someEvent', [1,2,3]);
}

ในที่สุดเมื่อคุณต้องการส่งเหตุการณ์จากตัวควบคุมลูกไปยังขอบเขตขึ้นไปคุณสามารถใช้ $ scope $ $ ปล่อย หากขอบเขตของ firstCtrl เป็นพาเรนต์ของขอบเขต secondCtrl:

function firstCtrl($scope){
    $scope.$on('someEvent', function(event, data) { console.log(data); });
}

function secondCtrl($scope){
    $scope.$emit('someEvent', [1,2,3]);
}

24

จิ๊กซอว์อีกสอง: (ไม่มีวิธีการให้บริการ)

1) สำหรับตัวควบคุมหลัก - ลูก - การใช้$scopeตัวควบคุมหลักเพื่อปล่อย / ออกอากาศเหตุการณ์ http://jsfiddle.net/laan_sachin/jnj6y/

2) การใช้งาน$rootScopeข้ามคอนโทรลเลอร์ที่ไม่เกี่ยวข้องกัน http://jsfiddle.net/VxafF/


อะไรเป็นสาเหตุของความซับซ้อนทั้งหมดนี้กับเหตุการณ์? ทำไมไม่ทำสิ่งนี้ jsfiddle.net/jnj6y/32
Dfr

มันขึ้นอยู่กับชนิดของความสัมพันธ์ Child Child ที่ถูกต้อง มันอาจจะเป็นทายาทของ DOM ก็คือในกรณีที่เหตุการณ์อนุญาตให้คุณแยกแยะสิ่งต่าง ๆ ได้
DarkKnight

17

ที่จริงแล้วการใช้ emit และ broadcast นั้นไม่มีประสิทธิภาพเพราะเหตุการณ์ที่เกิดขึ้นนั้นทำให้ลำดับขั้นของขอบเขตนั้นลดลงอย่างง่ายดายซึ่งสามารถลดระดับลงในขวดประสิทธิภาพสำหรับแอพพลิเคชั่นที่ซับซ้อนได้อย่างง่ายดาย

ฉันขอแนะนำให้ใช้บริการ นี่คือวิธีที่ฉันเพิ่งดำเนินการในหนึ่งในโครงการของฉัน - https://gist.github.com/3384419

แนวคิดพื้นฐาน - ลงทะเบียน pub-sub / event bus เป็นบริการ จากนั้นแทรกบัสเหตุการณ์นั้นซึ่งคุณต้องสมัครหรือเผยแพร่เหตุการณ์ / หัวข้อ


5

ฉันก็รู้วิธีนี้

angular.element($('#__userProfile')).scope().close();

แต่ฉันไม่ได้ใช้มันมากเกินไปเพราะฉันไม่ชอบใช้ตัวเลือก jQuery ในโค้ดเชิงมุม


คำตอบที่ดีที่สุด ง่ายและง่าย ... =)
zVictor

3
@zVictor นี่เป็นวิธีการสุดท้าย "สุดท้าย" มันใช้งานได้ แต่มันแตกออกจากขอบเขตเพื่อบังคับให้คุณย้อนกลับมาสิ่งนี้กำลังใช้การจัดการ DOM เพื่อบังคับให้ทำบางสิ่งบางอย่างแทนที่จะทำแบบนั้น ง่ายมันใช้งานได้ แต่ไม่สามารถปรับขนาดได้
ไบรอันโนอาห์

2
@BrianNoah จริง ไม่เป็นไรใช้รหัสนี้สำหรับต้นแบบหรือการทดลองบางอย่าง แต่ไม่ใช่สำหรับรหัสการผลิต
Andrey Korchak

1
นั่นเป็นสิ่งที่แย่ที่สุดที่สามารถทำได้ การจัดการ DOM ในบริการและการเข้าถึงขอบเขตโดยตรง
Mattia Franchetto

3

มีวิธีการที่ไม่ได้ขึ้นอยู่กับบริการหรือ$broadcast $emitมันไม่เหมาะในทุกกรณี แต่ถ้าคุณมีตัวควบคุมที่เกี่ยวข้อง 2 ตัวที่สามารถแยกออกเป็นคำสั่งได้คุณสามารถใช้requireตัวเลือกในข้อกำหนดของคำสั่ง นี่เป็นวิธีที่ ngModel และ ngForm สื่อสารกันมากที่สุด คุณสามารถใช้สิ่งนี้เพื่อสื่อสารระหว่างตัวควบคุมคำสั่งที่ซ้อนกันหรือในองค์ประกอบเดียวกัน

สำหรับสถานการณ์พาเรนต์ / ลูกการใช้จะเป็นดังนี้:

<div parent-directive>
  <div inner-directive></div>
</div>

และประเด็นหลักที่จะทำให้มันทำงาน: ในคำสั่งของผู้ปกครองด้วยวิธีการที่จะเรียกว่าคุณควรกำหนดพวกเขาในthis(ไม่ได้อยู่$scope):

controller: function($scope) {
  this.publicMethodOnParentDirective = function() {
    // Do something
  }
}

ในการกำหนดคำสั่งลูกคุณสามารถใช้requireตัวเลือกเพื่อให้ตัวควบคุมหลักถูกส่งผ่านไปยังฟังก์ชั่นการเชื่อมโยง (ดังนั้นคุณจึงสามารถเรียกใช้ฟังก์ชั่นได้จากscopeคำสั่งย่อย

require: '^parentDirective',
template: '<span ng-click="onClick()">Click on this to call parent directive</span>',
link: function link(scope, iElement, iAttrs, parentController) {
  scope.onClick = function() {
    parentController.publicMethodOnParentDirective();
  }
}

ด้านบนสามารถดูได้ที่http://plnkr.co/edit/poeq460VmQER8Gl9w8Oz?p=preview

คำสั่งพี่น้องใช้ในทำนองเดียวกัน แต่ทั้งสองคำสั่งในองค์ประกอบเดียวกัน:

<div directive1 directive2>
</div>

ใช้โดยการสร้างวิธีการในdirective1:

controller: function($scope) {
  this.publicMethod = function() {
    // Do something
  }
}

และใน directive2 นี้สามารถเรียกใช้โดยใช้requireตัวเลือกซึ่งส่งผลให้ siblingController ถูกส่งผ่านไปยังฟังก์ชันลิงก์:

require: 'directive1',
template: '<span ng-click="onClick()">Click on this to call sibling directive1</span>',
link: function link(scope, iElement, iAttrs, siblingController) {
  scope.onClick = function() {
    siblingController.publicMethod();
  }
}

นี้สามารถมองเห็นที่http://plnkr.co/edit/MUD2snf9zvadfnDXq85w?p=preview

การใช้งานของสิ่งนี้?

  • ผู้ปกครอง: กรณีใด ๆ ที่องค์ประกอบของเด็กจำเป็นต้อง "ลงทะเบียน" ตัวเองกับผู้ปกครอง เหมือนความสัมพันธ์ระหว่าง ngModel และ ngForm สิ่งเหล่านี้สามารถเพิ่มพฤติกรรมบางอย่างที่อาจส่งผลกระทบต่อโมเดล คุณอาจมีบางสิ่งบางอย่างจาก DOM อย่างแท้จริงเช่นกันซึ่งองค์ประกอบหลักจำเป็นต้องจัดการตำแหน่งของเด็กบางคนกล่าวว่าจัดการหรือตอบสนองต่อการเลื่อน

  • พี่น้อง: การสั่งให้มีการปรับเปลี่ยนพฤติกรรมของมัน ngModel เป็นกรณีคลาสสิกเพื่อเพิ่มตัวแยกวิเคราะห์ / การตรวจสอบเพื่อใช้งาน ngModel กับอินพุต


3

ฉันไม่รู้ว่านี่เป็นมาตรฐานหรือไม่ แต่ถ้าคุณมีคอนโทรลเลอร์ทั้งหมดในไฟล์เดียวกันคุณก็สามารถทำสิ่งนี้ได้:

app = angular.module('dashboardBuzzAdmin', ['ngResource', 'ui.bootstrap']);

var indicatorsCtrl;
var perdiosCtrl;
var finesCtrl;

app.controller('IndicatorsCtrl', ['$scope', '$http', function ($scope, $http) {
  indicatorsCtrl = this;
  this.updateCharts = function () {
    finesCtrl.updateChart();
    periodsCtrl.updateChart();
  };
}]);

app.controller('periodsCtrl', ['$scope', '$http', function ($scope, $http) {
  periodsCtrl = this;
  this.updateChart = function() {...}
}]);

app.controller('FinesCtrl', ['$scope', '$http', function ($scope, $http) {
  finesCtrl = this;
  this.updateChart = function() {...}
}]);

ดังที่คุณเห็นตัวบ่งชี้Ctrlกำลังเรียกฟังก์ชั่น updateChart ของตัวควบคุมอื่น ๆ ทั้งสองเมื่อเรียกใช้ UpdateCharts


2

คุณสามารถฉีดบริการ '$ controller' ในคอนโทรลเลอร์หลักของคุณ (MessageCtrl) แล้วสร้างอินสแตนซ์ / ฉีดคอนโทรลเลอร์ย่อย (DateCtrl) โดยใช้:
$scope.childController = $controller('childController', { $scope: $scope.$new() });

ตอนนี้คุณสามารถเข้าถึงข้อมูลจากตัวควบคุมลูกของคุณได้โดยการเรียกวิธีการต่าง ๆ เนื่องจากเป็นบริการ
แจ้งให้เราทราบหากมีปัญหาใด ๆ


1

ต่อไปนี้เป็นpublish-subscribeวิธีการที่ไม่คำนึงถึง Angular JS

ค้นหาตัวควบคุมพารามิเตอร์

//Note: Multiple entities publish the same event
regionButtonClicked: function () 
{
        EM.fireEvent('onSearchParamSelectedEvent', 'region');
},

plantButtonClicked: function () 
{
        EM.fireEvent('onSearchParamSelectedEvent', 'plant');
},

ตัวควบคุมตัวเลือกการค้นหา

//Note: It subscribes for the 'onSearchParamSelectedEvent' published by the Search Param Controller
localSubscribe: function () {
        EM.on('onSearchParamSelectedEvent', this.loadChoicesView, this);

});


loadChoicesView: function (e) {

        //Get the entity name from eData attribute which was set in the event manager
        var entity = $(e.target).attr('eData');

        console.log(entity);

        currentSelectedEntity = entity;
        if (entity == 'region') {
            $('.getvalue').hide();
            this.loadRegionsView();
            this.collapseEntities();
        }
        else if (entity == 'plant') {
            $('.getvalue').hide();
            this.loadPlantsView();
            this.collapseEntities();
        }


});

ผู้จัดการงานอีเว้นท์

myBase.EventManager = {

    eventArray:new Array(),


    on: function(event, handler, exchangeId) {
        var idArray;
        if (this.eventArray[event] == null) {
            idArray = new Array();
        } else { 
            idArray = this.eventArray[event];
        }
        idArray.push(exchangeId);
        this.eventArray[event] = idArray;

        //Binding using jQuery
        $(exchangeId).bind(event, handler);
    },

    un: function(event, handler, exchangeId) {

        if (this.eventArray[event] != null) {
            var idArray = this.eventArray[event];
            idArray.pop(exchangeId);
            this.eventArray[event] = idArray;

            $(exchangeId).unbind(event, handler);
        }
    },

    fireEvent: function(event, info) {
        var ids = this.eventArray[event];

        for (idindex = 0; idindex < ids.length; idindex++) {
            if (ids[idindex]) {

                //Add attribute eData
                $(ids[idindex]).attr('eData', info);
                $(ids[idindex]).trigger(event);
            }
        }
    }
};

ทั่วโลก

var EM = myBase.EventManager;

1

ในเชิงมุม 1.5 สามารถทำได้โดยทำสิ่งต่อไปนี้:

(function() {
  'use strict';

  angular
    .module('app')
    .component('parentComponent',{
      bindings: {},
      templateUrl: '/templates/products/product.html',
      controller: 'ProductCtrl as vm'
    });

  angular
    .module('app')
    .controller('ProductCtrl', ProductCtrl);

  function ProductCtrl() {
    var vm = this;
    vm.openAccordion = false;

    // Capture stuff from each of the product forms
    vm.productForms = [{}];

    vm.addNewForm = function() {
      vm.productForms.push({});
    }
  }

}());

นี่คือองค์ประกอบหลัก ในนี้ฉันได้สร้างฟังก์ชั่นที่ผลักวัตถุอื่นเข้าไปในproductFormsอาร์เรย์ของฉัน- หมายเหตุ - นี่เป็นเพียงตัวอย่างของฉันฟังก์ชั่นนี้สามารถเป็นอะไรก็ได้จริงๆ

ตอนนี้เราสามารถสร้างส่วนประกอบอื่นที่จะใช้ประโยชน์จากrequire:

(function() {
  'use strict';

  angular
    .module('app')
    .component('childComponent', {
      bindings: {},
      require: {
        parent: '^parentComponent'
      },
      templateUrl: '/templates/products/product-form.html',
      controller: 'ProductFormCtrl as vm'
    });

  angular
    .module('app')
    .controller('ProductFormCtrl', ProductFormCtrl);

  function ProductFormCtrl() {
    var vm = this;

    // Initialization - make use of the parent controllers function
    vm.$onInit = function() {
      vm.addNewForm = vm.parent.addNewForm;
    };  
  }

}());

นี่คือองค์ประกอบของลูกกำลังสร้างการอ้างอิงถึงฟังก์ชั่นองค์ประกอบผู้ปกครองaddNewFormซึ่งสามารถถูกผูกไว้กับ HTML และเรียกว่าฟังก์ชั่นอื่น ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.