动态控制器从范围绑定

时间:2013-07-21 18:02:54

标签: javascript angularjs

我想根据从后端收到的数据动态创建“组件”。目标是显示我的应用程序的一部分,而不使用服务器端模板:服务器发送包含应显示哪些组件的JSON数据,而不是显示服务器端组件。

这是我到目前为止所得到的:

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

module.controller('Ctrl1', ['$scope', function ($scope) {
    $scope.test = "test 1";
}])
.controller('Ctrl2', ['$scope', function ($scope) {
    $scope.test = "test 2";
}])
.controller('ComponentsController', ['$scope', function ($scope) {
    // this is JSON returned by backend
    $scope.components = [{
        name: "Wd1",
        controller: "Ctrl1",
    }, {
        name: "Wd2",
        controller: "Ctrl2",
    }];

    $scope.test = "test";
}]);

我的观点:

<div ng-app="testApp">
    <div ng-controller="ComponentsController">
        <div ng-repeat="component in components">
            <p>{{component.name}} - {{component.controller}}</p>
        </div>

        <div ng-repeat="component in components">
            <p ng-controller="component.controller">{{test}}</p>
        </div>
    </div>
</div>

但是,我收到以下错误:

  

错误:参数'component.controller'不是函数,得到字符串

我尝试编写一个指令,在编译期间分配控制器名称,但是在编译期间完成,它不能用于绑定......

这是一个小提琴:http://jsfiddle.net/mathieu/bTQA5/

3 个答案:

答案 0 :(得分:0)

将函数绑定到范围内的数据:

function ComponentsController($scope) {

    $scope.Ctrl1 = function () {
        $scope.test = "test 1";
    }

    $scope.Ctrl2 = function () {
        $scope.test = "test 2";
    }

    $scope.components = [{
        name: "Wd1",
        controller: $scope.Ctrl1
    }, {
        name: "Wd2",
        controller: $scope.Ctrl2
    }];

    $scope.test = "test";
}

这是updated jsFiddle

请注意,这里仍然存在逻辑问题;一旦控制器执行,{{ test }}绑定将被评估,因此结果文本(在每个绑定上)将是最后一次评估,即“Test 2”,在我们的例子中。

您可能希望将逻辑与处理程序联系起来,例如ng-click,按需执行:

<div ng-repeat="component in components">
    <button ng-controller="component.controller" 
            ng-click="component.controller()">
        Call {{ component.name }} controller
    </button>
</div>

这里是demonstrated live as well


此答案基于此问题的第一个版本,其中包含以下代码:

function ComponentsController($scope) {
    $scope.components = [{
        name: "Wd1",
        controller: "Ctrl1",
    }, {
        name: "Wd2",
        controller: "Ctrl2",
    }];

    $scope.test = "test";
}

function Ctrl1($scope) {
    $scope.test = "test 1";
}

function Ctrl2($scope) {
    $scope.test = "test 2";
}

答案 1 :(得分:0)

只需执行控制器名称,而不是字符串:

function ComponentsController($scope) {
    $scope.components = [{
        name: "Wd1",
        controller: Ctrl1,
    }, {
        name: "Wd2",
        controller: Ctrl2,
    }];

    $scope.test = "test";
}

答案 2 :(得分:0)

您可以使用以下指令,该指令将根据名称插入控制器:

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

module
.directive('dynamicController', ['$controller', function($controller) {
    return {
            restrict: 'A',
            scope: true,
            link: function (scope, element, attrs) {

                var locals = {
                    $scope: scope,
                    $element: element,
                    $attrs: attrs
                };

                element.data('$Controller', $controller(scope.$eval(attrs.dynamicController), locals));                       
            }
        };
    }
])

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

module
  .directive('dynamicController', ['$controller',
    function($controller) {
      return {
        restrict: 'A',
        scope: true,
        link: function(scope, element, attrs) {

          var locals = {
            $scope: scope,
            $element: element,
            $attrs: attrs
          };

          element.data('$Controller', $controller(scope.$eval(attrs.dynamicController), locals));
        }
      };
    }
  ])

.controller('Ctrl1', ['$scope',
    function($scope) {
      $scope.test = "test 1";
    }
  ])
  .controller('Ctrl2', ['$scope',
    function($scope) {
      $scope.test = "test 2";
    }
  ])
  .controller('ComponentsController', ['$scope',
    function($scope) {
      $scope.components = [{
        name: "Wd1",
        controller: "Ctrl1",
      }, {
        name: "Wd2",
        controller: "Ctrl2",
      }];

      $scope.test = "test";
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>

<div ng-app="testApp">
  <div ng-controller="ComponentsController">
    <div ng-repeat="component in components" dynamic-controller="component.controller">
      <p><span>{{test}}</span>
      </p>
    </div>
  </div>
</div>