300

ディレクティブがあります。コードは次のとおりです。

.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()コントローラーから呼び出す最良の方法は何ですか?

4

13 に答える 13

371

=分離されたスコープを使用する場合は、コントローラー スコープから変数の双方向バインディングを使用してコントロール オブジェクトを渡すことができます。同じコントロール オブジェクトを使用して、ページ上の同じディレクティブの複数のインスタンスを制御することもできます。

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>

于 2013-08-28T12:29:36.000 に答える
73

$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


@FlorianF のコメントによると、ディレクティブが分離スコープを使用する場合、事態はより複雑になります。これを機能させる 1 つの方法を次に示します。コントローラーにディレクティブ関数を登録する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

于 2013-06-04T00:57:26.693 に答える
15

オリバーの答えに基づいて構築する - ディレクティブの内部メソッドに常にアクセスする必要があるとは限らないかもしれません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
        };
      }
    }
  };
});
于 2014-03-16T01:13:31.810 に答える
2

scope.$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>
于 2016-01-29T18:29:28.977 に答える
2

メソッド名をディレクティブに伝えて、コントローラーから呼び出すものを定義できますが、スコープを分離する必要はありません。

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>

于 2016-02-16T11:49:17.430 に答える
0

ページコントローラーでディレクティブのコントローラーを取得する方法:

  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();
    

注: 指定されたソリューションは、要素ディレクティブのコントローラーに対してのみ機能します (タグ名は、必要なディレクティブの名前を取得するために使用されます)。

于 2016-11-21T10:32:19.490 に答える