在Angular指令中调用方法

时间:2015-06-18 10:24:01

标签: javascript angularjs

让我们说我有一个方法sayHelloWorld(),我想从我使用该指令的范围调用。我怎么能这样做?

另外,如果我在同一范围内有多个指令,那么如果整个事情变得更加困难,我将如何调用特定指令的方法?

Plunkr展示我想做的事:http://plnkr.co/edit/E6OLgnqArBx8lrw6s894?p=preview

2 个答案:

答案 0 :(得分:3)

你想要做的是创建一个公开你的API的服务,然后将服务注入你需要使用它的地方(注意,我在我的头上输入这个,所以这里可能存在语法错误,有):

var app = angular.module('MyApp', []);

/**
 * This service exposes one API method: saveDataToServer,
 * which is a methods that takes a string, and saves it
 * to some backend server.
 */
app.service('myService', function($http){

    /**
     * Save a string to some url.
     *
     * @param {string} str
     * @return Promise
     */
    this.saveDataToServer = function(str){
       return $http.post('/url/here/', {str: str});
    };
});

/**
 * This directive uses the service above, and calls 
 * the service's API method inside its onAction method,
 * which only this directive can access directly.
 */
app.directive('myDirective', function(){
    return {
        restrict: 'ea',
        scope: {
        },
        templateUrl: '/my-template.html',
        controller: function(myService){

            /**
             * This is a method that you can call from this
             * directive's template.
             */
            $scope.onAction = function(){

                // Inside this method, make a call to the service
                myService.saveDataToServer($scope.message).
                   then(function(res){
                       // data saved!
                   });
            };
        }
    };
});

// The template (/my-template.html)
<div>
    <input type="text" ng-model="message">
    <button ng-click="onAction()">Save</button>
</div>

// Your main template (/index.html)
<my-directive></my-directive>

您甚至可以在不同的控制器中重用您的服务,并在没有指令的情况下使用该服务:

app.controller('MyOtherController', function(myService){
    $scope.onSomeAction = function(str){
        myService.saveDataToServer(str).
           then(function(res){
               // data saved!
           });
    };
});

// Some template under the scope of MyOtherController
<div ng-controller="MyOtherController">
    <button ng-click="onSomeAction('hello world')">Hello</button>
</div>

现在,如果您只想从控制器检查指令内的数据,则只需将控制器中的数据绑定到指令中即可。当用户更改指令时,控制器中的数据将自动更改。您可以在控制器的$ scope中设置一个观察程序,以便在指令更改数据时触发事件,或者将控制器的回调传递给指令,这样该指令就可以告诉控制器数据已经发生了变化: p>

app.controller('MyController', function($scope){
    $scope.colors = [
       {color: 'Red'},
       {color: 'Green'},
       {color: 'Blue'}
    ];
});

app.directive('MyDirective', function(){
    return {
        scope: {
            colors: '='
        },
        templateUrl: '/my-template.html'
    };
});

// Template file: my-template.html
<div>
   <select ng-options="opt.color for opt in colors">
</div>

// index.html
<my-directive colors="colors"></my-directive>

根据您的要求,您可能还要考虑的是让指令从控制器获取数据,然后处理其自身内部的所有逻辑,而不是将数据发送回控制器并让控制器处理任何数据。逻辑。

例如,如果您的指令需要从用户那里获取一些输入并且数据需要保存在数据库中,请不要将数据从指令发送回控制器,并从控制器发送回服务器。只需将其从指令直接发送到服务器即可。然后,您可以重用该指令,而无需重写逻辑以将数据发送到服务器。

答案 1 :(得分:1)

解决方法之一是将控制器的对象(例如:exposedAPI)传递给指令的属性。然后,该指令将使用公开的函数填充此对象。

Plunkr

<强>控制器

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, $timeout) {

  $scope.exposedAPI = {};

  //Later in the code...
  $timeout(function() {

    $scope.exposedAPI.elmt_1.sayHello();

    //or

    $scope.exposedAPI.elmt_2.selectIndex(42);

    //or

    $scope.exposedAPI.elmt_3.changeDirectiveContent('Yeah !');

  });

});

<强>指令

app.directive("byteme", function() {
  return {
    scope: {
      'api': '='
    },
    template: '<div>{{content}}</div>',
    link: function(scope, element, attrs) {

      scope.content = 'Byteme directive!'

      //Exposed functions
      scope.api[attrs.id] = {
        sayHello: function() {

          console.log("Hello World !");

        },
        selectIndex: function(index) {

          console.log("Selected index: "+index);

        },
        changeDirectiveContent: function(newContent) {

          scope.content = newContent;

        }
      };

    }
  }
});

<强> HTML

<div byteme id="elmt_1" api="exposedAPI"></div>
<div byteme id="elmt_2" api="exposedAPI"></div>
<div byteme id="elmt_3" api="exposedAPI"></div>

<div ng-init="exposedAPI.elmt_1.changeDirectiveContent('YEAHHH')"></div> <!-- You can call API from the view directly -->