[Javascript] يمكن وحدة تحكم واحد نداء آخر؟


Answers

انظر هذا الكمان: http://jsfiddle.net/simpulton/XqDxG/

شاهد أيضا الفيديو التالي: التواصل بين المتحكمين

أتش تي أم أل:

<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>

جافا سكريبت:

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'];
Question

هل من الممكن أن تستخدم وحدة تحكم واحدة أخرى؟

فمثلا:

هذا المستند 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 والوصول إلى الخدمات.




فيما يلي نهج publish-subscribe بغض النظر عن JS Angular.

بحث تحكم بارام

//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;



هناك طريقة لا تعتمد على الخدمات أو $broadcast $emit أو $emit . وهو غير مناسب في جميع الحالات ، ولكن إذا كان لديك وحدتي تحكم ذات صلة يمكن تلخيصهما في توجيهات ، فيمكنك استخدام خيار الطلب في تعريف التوجيه. هذا على الأرجح كيف يتصل 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 يمكن استدعاء هذا باستخدام خيار الطلب الذي ينتج عنه تمرير 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 على المدخلات.




إذا كنت ترغب في استدعاء جهاز تحكم واحد إلى آخر هناك أربع طرق متاحة

  1. $ rootScope. $ emit () و $ rootScope. $ broadcast ()
  2. إذا كان المتحكم الثاني هو الطفل ، فيمكنك استخدام اتصال الطفل الرئيسي.
  3. استخدام الخدمات
  4. نوع الإختراق - بمساعدة الزاوي.الخدمة ()

1. $ rootScope. $ emit () و $ rootScope. $ broadcast ()

يمكن تحطيم وحدة التحكم ونطاقها ، ولكن يبقى rootScope $ عبر التطبيق ، ولهذا السبب نحن نتخذ $ rootScope لأن $ rootScope هو الأصل لجميع النطاقات.

إذا كنت تجري الاتصال من الوالدين إلى الطفل ، وحتى الطفل يريد التواصل مع أشقائه ، يمكنك استخدام بث $

إذا كنت تقوم بالتواصل من أحد الوالدين إلى أحد الوالدين ، فليس هناك إخوة يتم إخفاؤهم ، فيمكنك استخدام $ rootScope.

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' لن تستدعي داخل الأشقاء الأطفال وستستدعي داخل الوالدين فقط ، حيث يتم استدعاء البث الإذاعي داخل الأشقاء والأبوين كذلك. هذا هو المكان الذي يأتي فيه الأداء إلى العمل. إذا كنت تستخدم اتصال الوالدين إلى الطفل لأنه يتخطى بعض الشيكات القذرة.

2. إذا كان المتحكم الثاني هو الطفل ، فيمكنك استخدام اتصال الوالدين الطفل

إنها واحدة من أفضل الطرق ، إذا كنت ترغب في التواصل مع أحد الوالدين حيث يريد الطفل التواصل مع أحد الوالدين مباشرة ، فلن تحتاج إلى أي نوع من البث $ أو تنبعث منه $ ، ولكن إذا كنت ترغب في التواصل من الوالدين إلى الطفل ، فعليك استخدام الخدمة أو البث $

على سبيل المثال 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 Dependency Injection من 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. وفقًا لمستندات Angulars للخدمات Angular - يحصل كل مكون معتمد على خدمة على إشارة إلى المثيل المفرد الناتج عن مصنع الخدمة .

4. نوع الإختراق - بمساعدة angular.element ()

هذه الطريقة تحصل على النطاق () من العنصر بواسطة معرفته class.angular.element () معرف / فريد إرجاع العنصر والنطاق () يعطي متغير نطاق $ لمتغير آخر باستخدام متغير نطاق واحد لوحدة تحكم واحدة داخل آخر ليس ممارسة جيدة.

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.




اثنين من أكثر من العبث: (نهج غير الخدمة)

1) لوحدة تحكم الوالدين والطفل - باستخدام $scope وحدة تحكم الوالدين لتبث الأحداث / البث. http://jsfiddle.net/laan_sachin/jnj6y/

2) استخدام $rootScope عبر وحدات التحكم غير المتعلقة. jsfiddle.net/VxafF




أنا أعرف أيضا من هذا الطريق.

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

لكنني لا أستخدمها كثيرًا ، لأنني لا أحب استخدام أدوات اختيار jQuery في الشفرة الزاوية.




Links