从控制器继承隔离范围以生成可重用指令

时间:2016-05-18 06:54:15

标签: javascript angularjs

如何从控制器创建一个继承的隔离范围以生成可重用的指令?这是我的示例代码:

(function (app) {
    //declare the Template
    var template = function (element, attrs) {
        var htmltext =

            '<select ' + attrs.type +
            ' ng-init="getAll(\'' + attrs.classname +
            '\');" ng-model="' + attrs.model +
            '" ng-options="value.' + attrs.data +
            ' for value in result"></select>';

        return htmltext;
    };

    app.directive('listData', function () {
        return {
            restrict: 'E',
            controller: 'listController',
            controllerAs: 'vm',
            scope: { vm: '=' },
            template: template
        }
    });

}(angular.module('app')));

我们如何使用此指令中的多个(仅使用一个控制器)并使用控制器为指令生成的函数的结果。 在此示例中,我有一个getAll函数,它将$scope.result从控制器返回给调用者。我希望将这个结果与我给每个指令的ng-model一起使用。

    <div ng-controller="listController">
        <list-data type=""
                   model="person"
                   classname="Person"
                   data="Family" 
                   vm="listController">
        </list-data>
<list-data></list-data>
        <p>{{person.Name}} {{person.Family}}?</p>

和列表控制器:

(function (app) {

    app.controller('listController', ['$scope','myservice',function ($scope, myservice) {

        //Call GetAll Method From Each Class
        $scope.getAll = function (classname) {
            myservice.getAll(classname)
                .success(function (data, status) {
                    $scope.result = data;
                    $scope.status = status;
                })
                .error(function (data, status) {
                    $scope.result = data;
                    $scope.status = status;
                });
        }   
}(angular.module('app')));

和我的服务:

(function (app) {
    app.factory('myservice', function ($http,$q) {
        return {
            getAll: function (classname) {
                try {
                    return $http.get('/api/' + classname + '/GetAll/');
                } catch (e) {
                    window.alert(e.message);
                    //should Send a error to controller
                }
            }
        }
    });
}(angular.module('app')));

1 个答案:

答案 0 :(得分:0)

我想你想要这样的东西:

&#13;
&#13;
(function (app) {
    //declare the Template
    var template = function (element, attrs) {
        var htmltext =

            '<select ' + attrs.type +
            '  ng-model="model" ng-options="value as value[data] for value in from"></select>';

        return htmltext;
    };

    app.directive('listData', function () {
        return {
            restrict: 'E',
            scope: { data: '@',
                     classname:'@',
                     model:'=',
                     from:'=',
                     type:'@',
                     data:'@'
                   },
            template: template,
            replace:true,
        }
    });
    app.controller('TestController', ['$timeout', '$scope', function($timeout, $scope){
       $scope.data = [];
       $timeout(function(){
         $scope.data = [{Family:"FOO", Name:"foo"},{Family:"BAR", Name:"bar"}];
       });// simulate async fetching
    }])
}(angular.module('app', [])));
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="TestController">
         <h1> this is a test </h1>
         <list-data type=""
                   model="person"
                   classname="Person"
                   from="data"
                   data="Family">
        </list-data>

        <p>{{person.Name}} {{person.Family}}?</p>
  
  </div>
  </div>
&#13;
&#13;
&#13;

指令中的一些错误:

  1. 您想在<select>中选择一个人并展示他们的家人。为此,您必须使用as
  2. 中的可选ng-options
  3. 要正确使用隔离范围,您必须将数据绑定到它,这比使用attr更容易,特别是如果您希望列表能够更改并且您的指令需要刷新。
  4. 我添加了什么:

    1. 从属性到您的指令,在您的情况下,这是您要从中选择自己的人员列表。
    2. TestController是你的listController我还没有。它模拟异步提取。
    3. 我删除了什么:

      1. 在你的指令中调用getAll,这个指令处理带有一些参数的列表中一个元素的选择,而不是从你获取它的位置。这应该让视图的控制器被from属性替换。如果您确实想在指令中执行此操作,请使用函数link(scope, element, attrs){}执行提取并将数据绑定到范围。
      2. 编辑:根据要求,您可以将属性绑定到链接函数中的范围,但是这只能读取数据,而不是更改它们:

        link:function(scope, element, attrs){
            scope.value = attrs.myAttr;
            attrs.$observe('myAttr', function(){
              scope.value = attrs.myAttr;
            });
        }