一尘不染

使用ng-controller注入所需的依赖项

angularjs

使用ui.router,我们有一个状态控制器:

controller('widget', function($repository, $stateParams){
    $scope.widget = $repository.get($stateParams.id);
})

注册于:

.state('widget',
       controller: 'widget',
       template: '/widgetTemplate.html'

我们遇到了一种情况,我们希望将此控制器作为模板的一部分重复使用:

<div ng-controller="widget" ng-include="/widgetTemplate.html"></div>

但是似乎没有一种简单的方法来注入带有正确ID的模拟$ stateParams对象。就像是:

<div ng-controller="widget" ng-inject="{$stateParams: {id: 1234}}" ng-include="/widgetTemplate.html"></div>

除了编写增强ng-controller的自定义指令或重构我们的代码以利用继承的作用域之外,还有没有现成的方法可以做到这一点?


阅读 249

收藏
2020-07-04

共1个答案

一尘不染

我不认为有开箱即用的方法。ng-controller仅使用常规控制器实例化,就没有机会注入任何东西。

但这是一个有趣的“功能”,实际上,可以使用自定义指令相对简单地对其进行构建。

这是一个说明性的示例( 免责声明 :绝对不会在晦涩的场景下进行测试):

.directive("ngInject", function($parse, $interpolate, $controller, $compile) {
  return {
    terminal: true,
    transclude: true,
    priority: 510,
    link: function(scope, element, attrs, ctrls, transclude) {

      if (!attrs.ngController) {
        element.removeAttr("ng-inject");
        $compile(element)(scope);
        return;
      }

      var controllerName = attrs.ngController;

      var newScope = scope.$new(false);

      var locals = $parse(attrs.ngInject)(scope);
      locals.$scope = newScope;

      var controller = $controller(controllerName, locals);

      element.data("ngControllerController", controller);

      element.removeAttr("ng-inject").removeAttr("ng-controller");
      $compile(element)(newScope);
      transclude(newScope, function(clone){
        element.append(clone);
      });
      // restore to hide tracks
      element.attr("ng-controller", controllerName); 
    }
  };
});

用法如您所描述:

<div ng-controller="MainCtrl">
  {{name}}
  <div ng-controller="SecondCtrl" ng-inject="{foo: name, bar: 'bar'}">
  </div>
</div>

而且,当然,控制器可以注入以下变量:

.controller("SecondCtrl", function($scope, foo, bar){
});

矮人

2020-07-04