programing

Angular에 정의된 메서드를 호출하는 방법JS 디렉티브?

magicmemo 2023. 3. 22. 20:58
반응형

Angular에 정의된 메서드를 호출하는 방법JS 디렉티브?

지시사항이 있습니다. 코드는 다음과 같습니다.

.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()컨롤????

바인딩을 사용하여 할 수 .=컨트롤러 스코프에서 변수를 지정합니다.또한 동일한 컨트롤 오브젝트가 있는 페이지에서 동일한 디렉티브의 여러 인스턴스를 제어할 수도 있습니다.

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>

이 같은 합니다.$scope함수 '만일 수 있다'를하면 됩니다.updateMap$scope링크 기능 내에 있습니다.액션 버튼을 클릭하면 컨트롤러가 해당 함수를 호출할 수 있습니다.

<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


@@Florian의 코멘트대로,된 스코프를 상황이 .F의 코멘트는, 지시문이 고립된 범위를 사용한다면, 상황은 더 복잡해진다.요. 즉, '더하다'를 .set-fn map디렉티브 기능을 컨트롤러에 등록하는 디렉티브:

<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

오브젝트와의 통신을 용이하게 하기 위해 오브젝트를 디렉티브의 고립된 범위에서 공개하는 것은 유혹적일 수 있지만, 그렇게 하면 특히 이 통신을 2개의 레벨(컨트롤러, 디렉티브, 네스트 디렉티브 등)로 체인할 필요가 있는 경우, 혼란스러운 「스파게티」코드로 이어질 가능성이 있습니다.

원래 이 방법을 사용했지만, 몇 가지 조사 결과, 보다 합리적이고 읽기 쉬운 코드가 발견되어 서비스 경유로 통신에 사용하는 이벤트와 속성을 공개하는 것이 가능했습니다.그 결과, 디렉티브나 그 외의 컨트롤에 필요한 서비스 속성에 $watch를 사용하는 것으로 나타났습니다.이러한 변화에 대응하여 커뮤니케이션을 도모합니다.

이 추상화는 Angular와 매우 잘 어울립니다.이러한 이벤트에 대응해야 하는 모든 항목에 서비스를 주입할 수 있는 JS의 종속성 주입 프레임워크입니다.Angular.js 파일을 보면 이 명령어에서도 서비스와 $watch를 사용하는 것을 알 수 있습니다.이 명령어에서는 분리된 범위에서 이벤트가 노출되지 않습니다.

마지막으로 서로 의존적인 디렉티브 간에 커뮤니케이션이 필요한 경우 커뮤니케이션 수단으로 컨트롤러 공유를 권장합니다.

또한 AngularJS의 Wiki for Best Practices에는 다음과 같은 내용이 기재되어 있습니다.

atomic 이벤트에는 .$broadcast(), .$emit() 및 .$on()만 사용합니다.이 이벤트는 앱 전체에서 글로벌하게 관련됩니다(사용자 인증 또는 앱 닫기 등).모듈, 서비스 또는 위젯에 고유한 이벤트를 원하는 경우 서비스, Directive Controller 또는 서드파티 Libs를 고려해야 합니다.

  • 이벤트의 필요성 대신 $syslog.$watch()가 필요합니다.
  • 서비스나 호출 방법을 직접 투입하는 것도 직접적인 커뮤니케이션에 도움이 됩니다.
  • 디렉티브는 디렉티브 컨트롤러를 통해 서로 직접 통신할 수 있습니다.

Oliver의- 메서드에 항상 이 공백 또한 이 경우 빈 객체를 생성하여 명령어를 추가할 필요가 없습니다.control오류 발생)cannot set property 'takeTablet' of undefined

지시문 내의 다른 장소에서도 메서드를 사용할 수 있습니다.

하겠습니다.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
        };
      }
    }
  };
});

솔직히 말해서, 나는 이 문제에 대한 어떤 대답도 납득할 수 없었다.자, 제 해결책은 다음과 같습니다.

Directive Handler(Manager) 접근법

가 'Directive'인지 사용할 수 있습니다.$scope 된 것입니다.

A 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;
    }
});

지시 코드는 보통 DOM을 다루지 않는 모든 논리를 지시 컨트롤러 안에 넣습니다.그리고 컨트롤러 인스턴스를 우리 핸들러에 등록한다.

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>

$140 사용 및 컨트롤러 등록$parent 이 은 고립된 스프 isolated 에서는 작동하지 이 기술은 격리된 상태에서는 작동하지 않습니다.$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();
    };
});

조금 늦었지만, 이것은 디렉티브의 함수를 호출하기 위한 분리된 범위와 "이벤트"를 가진 솔루션입니다.이 솔루션은 satchmorunSO 게시물에서 영감을 얻어 모듈과 API를 추가합니다.

//Create module
var MapModule = angular.module('MapModule', []);

//Load dependency dynamically
angular.module('app').requires.push('MapModule');

디렉티브와 통신할 API를 만듭니다.addUpdateEvent는 이벤트 배열에 이벤트를 추가하고 updateMap은 모든 이벤트 함수를 호출합니다.

MapModule.factory('MapApi', function () {
    return {
        events: [],

        addUpdateEvent: function (func) {
            this.events.push(func);
        },

        updateMap: function () {
            this.events.forEach(function (func) {
                func.call();
            });
        }
    }
});

(이벤트를 삭제하려면 기능을 추가해야 할 수 있습니다).

지시문에서 MapAPI에 대한 참조를 설정하고 MapApi.updateMap이 호출될 때 이벤트로 $scope.updateMap을 추가합니다.

app.directive('map', function () {
    return {
        restrict: 'E', 
        scope: {}, 
        templateUrl: '....',
        controller: function ($scope, $http, $attrs, MapApi) {

            $scope.api = MapApi;

            $scope.updateMap = function () {
                //Update the map 
            };

            //Add event
            $scope.api.addUpdateEvent($scope.updateMap);

        }
    }
});

메인 컨트롤러에서 MapApi에 대한 참조를 추가하고 MapApi.updateMap()을 호출하여 맵을 업데이트합니다.

app.controller('mainController', function ($scope, MapApi) {

    $scope.updateMapButtonClick = function() {
        MapApi.updateMap();    
    };
}

디렉티브가 상위 범위에서 함수를 정의할 수 있도록 하는 데 사용할 수 있는 DOM 속성을 지정할 수 있습니다.부모 스코프는 다른 메서드와 마찬가지로 이 메서드를 호출할 수 있습니다.여기 플런커가 있어요.다음은 관련 코드입니다.

clearfn는 부모 스코프가 스코프 속성을 전달할 수 있는 디렉티브 요소의 어트리뷰트입니다.이러한 속성을 디렉티브가 원하는 동작을 실행하는 함수로 설정할 수 있습니다.

<!DOCTYPE html>
<html ng-app="myapp">
  <head>
    <script data-require="angular.js@*" 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>

스코프를 사용합니다.$parent - 호출된 함수를 디렉티브 함수에 관련짓습니다.

angular.module('myApp', [])
.controller('MyCtrl',['$scope',function($scope) {

}])
.directive('mydirective',function(){
 function link(scope, el, attr){
   //use scope.$parent to associate the function called to directive function
   scope.$parent.myfunction = function directivefunction(parameter){
     //do something
}
}
return {
        link: link,
        restrict: 'E'   
      };
});

HTML로

<div ng-controller="MyCtrl">
    <mydirective></mydirective>
    <button ng-click="myfunction(parameter)">call()</button>
</div>

명령어에 메서드 이름을 지정하여 컨트롤러에서 호출하는 것을 정의할 수 있습니다.단, 분리된 스코프는 사용할 수 없습니다.

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>

테스트 완료 이것이 도움이 되길 바랍니다.

간단한 접근법(태그를 원래 코드로 생각)

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

이게 최선의 선택은 아닐지 몰라도 넌 할 수 있어angular.element("#element").isolateScope()또는$("#element").isolateScope()명령의 범위 및/또는 컨트롤러에 액세스합니다.

페이지 컨트롤러에서 디렉티브의 컨트롤러를 얻는 방법:

  1. 커스텀 디렉티브를 작성하여 DOM 요소에서 디렉티브컨트롤러에 대한 참조를 가져옵니다.

    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. 페이지 컨트롤러의 html에서 사용합니다.

    <my-directive controller="vm.myDirectiveController"></my-directive>
    
  3. 페이지 컨트롤러에서 디렉티브컨트롤러를 사용합니다.

    vm.myDirectiveController.callSomeMethod();
    

주의: 지정된 솔루션은 요소 디렉티브의 컨트롤러에서만 작동합니다(태그 이름은 원하는 디렉티브의 이름을 얻기 위해 사용됩니다).

다음 솔루션은 컨트롤러(부모 및 디렉티브 모두)를 '컨트롤러 A' 형식으로 사용하는 경우에 도움이 됩니다.

이게 유용하다고 생각하실 수도 있지만

지시:

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

언급URL : https://stackoverflow.com/questions/16881478/how-to-call-a-method-defined-in-an-angularjs-directive

반응형