angularjs - एंगुलरजेएस निर्देश में परिभाषित विधि को कैसे कॉल करें?





angularjs-directive (12)


परीक्षण आशा है कि यह किसी की मदद करता है।

मेरा सरल दृष्टिकोण (टैग को अपने मूल कोड के रूप में सोचें)

<html>
<div ng-click="myfuncion"> 
<my-dir callfunction="myfunction">
</html>

<directive "my-dir">
callfunction:"=callfunction"
link : function(scope,element,attr) {
scope.callfunction = function() {
 /// your code
}
}
</directive>

मेरे पास निर्देश है, यहां कोड है:

.directive('map', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function($scope, element, attrs) {

            var center = new google.maps.LatLng(50.1, 14.4); 
            $scope.map_options = {
                zoom: 14,
                center: center,
                mapTypeId: google.maps.MapTypeId.ROADMAP
            };
            // create map
            var map = new google.maps.Map(document.getElementById(attrs.id), $scope.map_options);
            var dirService= new google.maps.DirectionsService();
            var dirRenderer= new google.maps.DirectionsRenderer()

            var showDirections = function(dirResult, dirStatus) {
                if (dirStatus != google.maps.DirectionsStatus.OK) {
                    alert('Directions failed: ' + dirStatus);
                    return;
                  }
                  // Show directions
                dirRenderer.setMap(map);
                //$scope.dirRenderer.setPanel(Demo.dirContainer);
                dirRenderer.setDirections(dirResult);
            };

            // Watch
            var updateMap = function(){
                dirService.route($scope.dirRequest, showDirections); 
            };    
            $scope.$watch('dirRequest.origin', updateMap);

            google.maps.event.addListener(map, 'zoom_changed', function() {
                $scope.map_options.zoom = map.getZoom();
              });

            dirService.route($scope.dirRequest, showDirections);  
        }
    }
})

मैं उपयोगकर्ता कार्रवाई पर updateMap() को कॉल करना चाहता हूं। कार्रवाई बटन निर्देश पर नहीं है।

नियंत्रक से updateMap() को कॉल करने का सबसे अच्छा तरीका क्या है?




आप एक डोम विशेषता निर्दिष्ट कर सकते हैं जिसका उपयोग माता-पिता को दायरे के दायरे पर फ़ंक्शन को परिभाषित करने की अनुमति देने के लिए किया जा सकता है। माता-पिता का दायरा तब इस विधि को किसी अन्य की तरह कॉल कर सकता है। Here's एक प्लंकर है। और नीचे प्रासंगिक कोड है।

clearfn निर्देश तत्व पर एक विशेषता है जिसमें अभिभावक का दायरा एक स्कोप संपत्ति को पारित कर सकता है, जिसके बाद निर्देश किसी वांछित व्यवहार को पूरा करने वाले फ़ंक्शन पर सेट कर सकता है।

<!DOCTYPE html>
<html ng-app="myapp">
  <head>
    <script data-require="[email protected]*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <style>
      my-box{
        display:block;
        border:solid 1px #aaa;
        min-width:50px;
        min-height:50px;
        padding:.5em;
        margin:1em;
        outline:0px;
        box-shadow:inset 0px 0px .4em #aaa;
      }
    </style>
  </head>
  <body ng-controller="mycontroller">
    <h1>Call method on directive</h1>
    <button ng-click="clear()">Clear</button>
    <my-box clearfn="clear" contentEditable=true></my-box>
    <script>
      var app = angular.module('myapp', []);
      app.controller('mycontroller', function($scope){
      });
      app.directive('myBox', function(){
        return {
          restrict: 'E',
          scope: {
            clearFn: '=clearfn'
          },
          template: '',
          link: function(scope, element, attrs){
            element.html('Hello World!');
            scope.clearFn = function(){
              element.html('');
            };
          }
        }
      });
    </script>
  </body>
</html>



यह मानते हुए कि एक्शन बटन निर्देश के रूप में एक ही नियंत्रक $scope का उपयोग करता है, बस लिंक फ़ंक्शन के अंदर $scope पर फ़ंक्शन updateMap को परिभाषित करता है। जब कार्रवाई बटन क्लिक किया जाता है तो आपका नियंत्रक तब उस फ़ंक्शन को कॉल कर सकता है।

<div ng-controller="MyCtrl">
    <map></map>
    <button ng-click="updateMap()">call updateMap()</button>
</div>
app.directive('map', function() {
    return {
        restrict: 'E',
        replace: true,
        template: '<div></div>',
        link: function($scope, element, attrs) {
            $scope.updateMap = function() {
                alert('inside updateMap()');
            }
        }
    }
});

fiddle

@ फ्लोरियनएफ की टिप्पणी के अनुसार, यदि निर्देश एक अलग दायरे का उपयोग करता है, तो चीजें अधिक जटिल होती हैं। इसे काम करने का एक तरीका यहां दिया गया है: map निर्देश में एक set-fn विशेषता जोड़ें जो नियंत्रक के साथ निर्देश फ़ंक्शन पंजीकृत करेगा:

<map set-fn="setDirectiveFn(theDirFn)"></map>
<button ng-click="directiveFn()">call directive function</button>
scope: { setFn: '&' },
link: function(scope, element, attrs) {
    scope.updateMap = function() {
       alert('inside updateMap()');
    }
    scope.setFn({theDirFn: scope.updateMap});
}
function MyCtrl($scope) {
    $scope.setDirectiveFn = function(directiveFn) {
        $scope.directiveFn = directiveFn;
    };
}

fiddle




आप विधि नाम को निर्देशित करने के लिए निर्देश दे सकते हैं कि आप नियंत्रक से कॉल करना चाहते हैं लेकिन बिना किसी गुंजाइश के,

angular.module("app", [])
  .directive("palyer", [
    function() {
      return {
        restrict: "A",
        template:'<div class="player"><span ng-bind="text"></span></div>',
        link: function($scope, element, attr) {
          if (attr.toPlay) {
            $scope[attr.toPlay] = function(name) {
              $scope.text = name + " playing...";
            }
          }
        }
      };
    }
  ])
  .controller("playerController", ["$scope",
    function($scope) {
      $scope.clickPlay = function() {
        $scope.play('AR Song');
      };
    }
  ]);
.player{
  border:1px solid;
  padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  <div ng-controller="playerController">
    <p>Click play button to play
      <p>
        <p palyer="" to-play="play"></p>
        <button ng-click="clickPlay()">Play</button>

  </div>
</div>




यद्यपि यह इसके साथ संवाद करने के लिए निर्देश के अलग-अलग दायरे पर किसी ऑब्जेक्ट का पर्दाफाश करने के लिए मोहक हो सकता है, लेकिन "स्पैगेटी" कोड को भ्रमित करने के कारण, विशेष रूप से यदि आपको इस स्तर को दो स्तरों (नियंत्रक, निर्देश, घोंसला निर्देश, इत्यादि)

हम मूल रूप से इस पथ से नीचे चले गए लेकिन कुछ और शोधों के बाद यह अधिक समझ में आया और परिणामस्वरूप घटनाओं और गुणों का खुलासा करने के लिए दोनों अधिक रखरखाव और पठनीय कोड दोनों में एक निर्देश के माध्यम से संचार के लिए उपयोग किया जाएगा, फिर उस सेवा के गुणों पर $ घड़ी का उपयोग करके निर्देश या किसी भी अन्य नियंत्रण जो संचार के लिए उन परिवर्तनों पर प्रतिक्रिया करने की आवश्यकता होगी।

यह अमूर्त AngularJS के निर्भरता इंजेक्शन ढांचे के साथ बहुत अच्छी तरह से काम करता है क्योंकि आप उन घटनाओं पर प्रतिक्रिया करने की आवश्यकता वाले किसी भी आइटम में सेवा इंजेक्ट कर सकते हैं। यदि आप Angular.js फ़ाइल देखते हैं, तो आप देखेंगे कि वहां के निर्देश भी सेवाओं का उपयोग करते हैं और इस तरीके से $ घड़ी देखते हैं, वे अलग-अलग दायरे पर घटनाओं का पर्दाफाश नहीं करते हैं।

अंत में, यदि आपको एक दूसरे पर निर्भर निर्देशों के बीच संवाद करने की आवश्यकता है, तो मैं उन निर्देशों के बीच संचार के माध्यम के रूप में नियंत्रक साझा करने की अनुशंसा करता हूं।

सर्वोत्तम अभ्यासों के लिए एंगुलरजेएस की विकी यह भी उल्लेख करती है:

केवल एटमिक घटनाओं के लिए $ $ प्रसारण (), $ emit () और। $ On () का उपयोग करें, जो पूरे ऐप में वैश्विक रूप से प्रासंगिक हैं (जैसे उपयोगकर्ता प्रमाणीकरण या ऐप बंद करना)। यदि आप मॉड्यूल, सेवाओं या विजेट्स के लिए विशिष्ट घटनाएं चाहते हैं, तो आपको सेवाओं, निर्देशक नियंत्रक, या तृतीय पक्ष लिब्स पर विचार करना चाहिए

  • $ स्कोप। $ घड़ी () घटनाओं की आवश्यकता को प्रतिस्थापित करना चाहिए
  • प्रत्यक्ष संचार के लिए सीधे इंजेक्शन सेवाएं और कॉलिंग विधियां भी उपयोगी होती हैं
  • निर्देश सीधे-नियंत्रक के माध्यम से एक दूसरे के साथ संवाद करने में सक्षम हैं



पृष्ठ नियंत्रक में निर्देशक नियंत्रक कैसे प्राप्त करें:

  1. डीओएम तत्व से निर्देश नियंत्रक के संदर्भ प्राप्त करने के लिए एक कस्टम निर्देश लिखें:

    angular.module('myApp')
        .directive('controller', controller);
    
    controller.$inject = ['$parse'];
    
    function controller($parse) {
        var directive = {
            restrict: 'A',
            link: linkFunction
        };
        return directive;
    
        function linkFunction(scope, el, attrs) {
            var directiveName = attrs.$normalize(el.prop("tagName").toLowerCase());
            var directiveController = el.controller(directiveName);
    
            var model = $parse(attrs.controller);
            model.assign(scope, directiveController);
        }
    }
    
  2. पेज नियंत्रक के एचटीएमएल में इसका इस्तेमाल करें:

    <my-directive controller="vm.myDirectiveController"></my-directive>
    
  3. पेज नियंत्रक में निर्देश नियंत्रक का प्रयोग करें:

    vm.myDirectiveController.callSomeMethod();
    

नोट: दिया गया समाधान केवल तत्व निर्देशकों के नियंत्रकों के लिए काम करता है (टैग नाम वांछित निर्देश का नाम पाने के लिए उपयोग किया जाता है)।




ओलिवर के उत्तर पर बिल्डिंग - आपको हमेशा निर्देशक के आंतरिक तरीकों तक पहुंचने की आवश्यकता नहीं होती है, और उन मामलों में आप शायद एक खाली वस्तु बनाना नहीं चाहते हैं और निर्देश को control एआरआर जोड़ना चाहते हैं ताकि इसे किसी त्रुटि को फेंकने से रोका जा सके ( cannot set property 'takeTablet' of undefined )।

आप भी निर्देश के भीतर अन्य स्थानों में विधि का उपयोग करना चाह सकते हैं।

मैं यह सुनिश्चित करने के लिए एक चेक scope.control कि scope.control मौजूद है, और प्रकट मॉड्यूल पैटर्न के समान तरीके से इसे सेट करें

app.directive('focusin', function factory() {
  return {
    restrict: 'E',
    replace: true,
    template: '<div>A:{{control}}</div>',
    scope: {
      control: '='
    },
    link : function (scope, element, attrs) {
      var takenTablets = 0;
      var takeTablet = function() {
        takenTablets += 1;  
      }

      if (scope.control) {
        scope.control = {
          takeTablet: takeTablet
        };
      }
    }
  };
});



यदि आप अलग-अलग क्षेत्रों का उपयोग करना चाहते हैं तो आप नियंत्रक दायरे से एक चर के द्वि-दिशात्मक बाध्यकारी = का उपयोग कर नियंत्रण ऑब्जेक्ट पास कर सकते हैं। आप उसी नियंत्रण ऑब्जेक्ट वाले पृष्ठ पर उसी निर्देश के कई उदाहरण भी नियंत्रित कर सकते हैं।

angular.module('directiveControlDemo', [])

.controller('MainCtrl', function($scope) {
  $scope.focusinControl = {};
})

.directive('focusin', function factory() {
  return {
    restrict: 'E',
    replace: true,
    template: '<div>A:{{internalControl}}</div>',
    scope: {
      control: '='
    },
    link: function(scope, element, attrs) {
      scope.internalControl = scope.control || {};
      scope.internalControl.takenTablets = 0;
      scope.internalControl.takeTablet = function() {
        scope.internalControl.takenTablets += 1;
      }
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="directiveControlDemo">
  <div ng-controller="MainCtrl">
    <button ng-click="focusinControl.takeTablet()">Call directive function</button>
    <p>
      <b>In controller scope:</b>
      {{focusinControl}}
    </p>
    <p>
      <b>In directive scope:</b>
      <focusin control="focusinControl"></focusin>
    </p>
    <p>
      <b>Without control object:</b>
      <focusin></focusin>
    </p>
  </div>
</div>




हो सकता है कि यह सबसे अच्छा विकल्प न हो, लेकिन आप angular.element("#element").isolateScope() कर सकते हैं angular.element("#element").isolateScope() या $("#element").isolateScope() को अपने दायरे के दायरे और / या नियंत्रक तक पहुंचने के लिए।




ईमानदार होने के लिए, मैं वास्तव में इस धागे में किसी भी उत्तर के साथ आश्वस्त नहीं था। तो, यहां मेरे समाधान हैं:

निर्देश हैंडलर (प्रबंधक) दृष्टिकोण

यह विधि अज्ञात है कि निर्देश का $scope एक साझा या अलग है या नहीं

निर्देशक उदाहरण पंजीकृत करने के लिए एक factory

angular.module('myModule').factory('MyDirectiveHandler', function() {
    var instance_map = {};
    var service = {
        registerDirective: registerDirective,
        getDirective: getDirective,
        deregisterDirective: deregisterDirective
    };

    return service;

    function registerDirective(name, ctrl) {
        instance_map[name] = ctrl;
    }

    function getDirective(name) {
        return instance_map[name];
    }

    function deregisterDirective(name) {
        instance_map[name] = null;
    }
});

निर्देश कोड, मैं आमतौर पर सभी तर्क डालता हूं जो निर्देशक नियंत्रक के अंदर डीओएम से निपटता नहीं है। और हमारे हैंडलर के अंदर नियंत्रक उदाहरण दर्ज करना

angular.module('myModule').directive('myDirective', function(MyDirectiveHandler) {
    var directive = {
        link: link,
        controller: controller
    };

    return directive;

    function link() {
        //link fn code
    }

    function controller($scope, $attrs) {
        var name = $attrs.name;

        this.updateMap = function() {
            //some code
        };

        MyDirectiveHandler.registerDirective(name, this);

        $scope.$on('destroy', function() {
            MyDirectiveHandler.deregisterDirective(name);
        });
    }
})

टेम्पलेट कोड

<div my-directive name="foo"></div>

factory का उपयोग कर नियंत्रक उदाहरण तक पहुंचें और सार्वजनिक रूप से उजागर विधियों को चलाएं

angular.module('myModule').controller('MyController', function(MyDirectiveHandler, $scope) {
    $scope.someFn = function() {
        MyDirectiveHandler.get('foo').updateMap();
    };
});

कोणीय दृष्टिकोण

कोणीय की किताब से बाहर एक पत्ता लेना कि वे किस तरह से निपटते हैं

<form name="my_form"></form>

$parse का उपयोग करके और $parent दायरे पर नियंत्रक को पंजीकृत करना। यह तकनीक अलग-अलग $scope निर्देशों पर काम नहीं करती है।

angular.module('myModule').directive('myDirective', function($parse) {
    var directive = {
        link: link,
        controller: controller,
        scope: true
    };

    return directive;

    function link() {
        //link fn code
    }

    function controller($scope, $attrs) {
        $parse($attrs.name).assign($scope.$parent, this);

        this.updateMap = function() {
            //some code
        };
    }
})

$scope.foo का उपयोग कर नियंत्रक के अंदर इसे एक्सेस करें

angular.module('myModule').controller('MyController', function($scope) {
    $scope.someFn = function() {
        $scope.foo.updateMap();
    };
});



समाधान के नीचे उपयोगी होगा, जब आपके पास नियंत्रक (माता-पिता और निर्देश दोनों) अलग-अलग होते हैं (नियंत्रक के रूप में 'प्रारूप में

किसी को यह उपयोगी मिल सकता है,

निर्देश:

var directive = {
        link: link,
        restrict: 'E',
        replace: true,
        scope: {
            clearFilters: '='
        },
        templateUrl: "/temp.html",
        bindToController: true, 
        controller: ProjectCustomAttributesController,
        controllerAs: 'vmd'
    };
    return directive;

    function link(scope, element, attrs) {
        scope.vmd.clearFilters = scope.vmd.SetFitlersToDefaultValue;
    }
}

निर्देश नियंत्रक:

function DirectiveController($location, dbConnection, uiUtility) {
  vmd.SetFitlersToDefaultValue = SetFitlersToDefaultValue;

function SetFitlersToDefaultValue() {
           //your logic
        }
}

HTML कोड :

      <Test-directive clear-filters="vm.ClearFilters"></Test-directive>
    <a class="pull-right" style="cursor: pointer" ng-click="vm.ClearFilters()"><u>Clear</u></a> 
//this button is from parent controller which will call directive controller function



AngularJS में, हम अपने मॉडल अपडेट करते हैं, और हमारे विचार / टेम्पलेट डीओएम को स्वचालित रूप से अपडेट करते हैं (अंतर्निर्मित या कस्टम निर्देशों के माध्यम से)।

स्कोप विधियों के रूप में $ लागू और $ घड़ी, डीओएम से संबंधित नहीं हैं।

Concepts पृष्ठ (अनुभाग "रनटाइम") में $ पाचन लूप, $ लागू, $ evalAsync कतार और $ घड़ी सूची का एक बहुत अच्छा स्पष्टीकरण है। पाठ के साथ चित्र यहां दिया गया है:

जो भी कोड किसी दायरे तक watchExpression - आम तौर पर नियंत्रक और निर्देश (उनके लिंक फ़ंक्शंस और / या उनके नियंत्रक) - एक " watchExpression " सेट कर सकते हैं जो AngularJS उस दायरे के विरुद्ध मूल्यांकन करेगा। यह मूल्यांकन तब होता है जब AngularJS अपने $ पाचन लूप (विशेष रूप से, "$ घड़ी सूची" पाश) में प्रवेश करता है। आप व्यक्तिगत स्कोप गुण देख सकते हैं, आप एक साथ दो गुणों को देखने के लिए एक फ़ंक्शन को परिभाषित कर सकते हैं, आप एक सरणी की लंबाई देख सकते हैं आदि।

जब चीजें "AngularJS के अंदर होती हैं" - उदाहरण के लिए, आप एक टेक्स्टबॉक्स में टाइप करते हैं जिसमें AngularJS दो-तरफा डाटाबेसिंग सक्षम है (यानी, एनजी-मॉडल का उपयोग करता है), एक $ http कॉलबैक आग, आदि - $ आवेदन पहले से ही कॉल किया जा चुका है, इसलिए हम उपरोक्त आकृति में "AngularJS" आयताकार के अंदर फिर से है। सभी watchExpressions का मूल्यांकन किया जाएगा (संभवतः एक से अधिक बार - जब तक कोई और परिवर्तन नहीं पता चला)।

जब चीजें "AngularJS के बाहर होती हैं" - उदाहरण के लिए, आपने निर्देश में बाध्य () का उपयोग किया और फिर उस घटना को आग लग गई, जिसके परिणामस्वरूप आपका कॉलबैक बुलाया गया, या कुछ jQuery पंजीकृत कॉलबैक आग - हम अभी भी "मूल" आयताकार में हैं। यदि कॉलबैक कोड कुछ भी संशोधित करता है कि कोई भी $ घड़ी देख रही है, तो AngularJS आयताकार में प्रवेश करने के लिए $ $ पर कॉल करें, जिससे $ पाचन लूप चलने का कारण बनता है, और इसलिए AngularJS परिवर्तन को नोटिस करेगा और उसका जादू करेगा।





angularjs angularjs-directive