【问题标题】:Dynamically assign ng-controller on runtime在运行时动态分配 ng-controller
【发布时间】:2014-08-29 15:23:32
【问题描述】:

我有一种情况需要动态更改控制器,以便相应地影响范围变量。一般结构:

<div ng-controller="GameController">
   // some general HTML which fits all types of games
    <div ng-controller="someScopeVar"> // Type of game
      // some game-type-specific ng-models that should respond to the change of controller, i.e scope
    </div
</div>

我看到here 可以在ng-repeat 内完成。可以在外面做吗? 换句话说,我可以告诉 Angular 将其作为变量而不是字符串文字来读取吗?

【问题讨论】:

  • 我认为这个问题具有误导性。你真的想动态设置控制器,还是只是改变 $scope 的内容?
  • someScopeVar应该是控制器函数,你现在用什么值?
  • @Grundy,你是对的。我为控制器使用了一个字符串文字,它是在范围之外定义的,而不是将控制器本身分配给someScopeVal。请作为答案发布
  • @Grundy,这适用于初始分配,但是当我尝试更改它以响应用户点击事件时,它保持原样
  • 你应该尝试深入观察ui-router这里有一些(最新)链接到超级基本资源stackoverflow.com/a/20581135/1679310。此功能实际上是一个状态机,旨在根据状态更改更改应用程序的某些部分(可能依赖于 url 但并非必须)。您将只管理您的状态,这些状态可能有许多带有相关控制器的内部视图。更改状态 - 将注入具有不同控制器的相同视图(模板)......真的请尝试观察;)

标签: javascript angularjs


【解决方案1】:

正如 cmets 中所讨论的,angular 有一个非常强大的功能/库来处理这些场景 - ui-router (以及其强大的wiki

ui-router 是需要开发功能部件的答案 - 状态,而不是在视图/url (引用自主页):: p>

AngularUI Router 是 AngularJS 的一个路由框架,它允许您将界面的各个部分组织成一个状态机。不同于 Angular ngRoute 模块中的 $route 服务,它是围绕 URL 路由组织的,UI-Router 是围绕 states 组织的,它可以选择有路由,以及其他行为,附上。

有一些非常有趣的博文:

...关于 AngularJS 的新路由器,最有趣的不是路由器本身,而是它附带的状态管理器。您不是针对一个控制器/视图来呈现给定的 url,而是针对一个状态。状态在层次结构中进行管理,提供父状态的继承和页面组件的复杂组合,同时在本质上保持声明性......

...ui-router 完全包含路由系统的状态机特性。它允许您定义状态,并将您的应用程序转换到这些状态。真正的胜利在于它允许您解耦嵌套状态,并以优雅的方式进行一些非常复杂的布局。

正是我们需要的点 - 解耦子状态... 实际上动态更改控制器 ...可以通过 url 更改或只是状态更改 (一个兄弟孩子而不是其他不改变网址)

您需要以不同的方式考虑您的路由,但是一旦您了解了基于状态的方法,我想您会喜欢它...

最后,链接很少,我将其标记为ui-router的圣杯

  • Sample application。在行动中,我们可以看到 ui-router 状态机是如何工作的。我们可以将 list 加载为 父状态,然后我们可以选择行项目,它们确实代表了它们自己的 子状态...而父是不重新加载here我试图解释得更详细)

  • state.js - 示例应用程序的基本代码。这是我见过的最好的文档化代码 sn-ps 之一...花了一些时间来阅读,这将为您提供 80% 的答案:ui-Router 是如何工作的

根据我的经验,这确实适用于小型应用程序以及大型系统......喜欢它......

【讨论】:

    【解决方案2】:

    ngRepeat 的工作方式不同。它之所以有效,是因为它编译了每次重复,这是您需要在这里做的。

    例如:

    mainCtrl = function($scope, $compile, $element) {
        $scope.someScopeVar = ctrl1;
        $scope.changeCtrl = function(id) {
            $scope.someScopeVar = id === 1 ? ctrl1 : ctrl2;
            var elm = $element.find('div');
            elm.replaceWith($compile(template)($scope));
        }
    }
    
    var ctrl1 = function($scope) { 
      $scope.name = 'World';
    }
    
    var ctrl2 = function($scope) {      
      $scope.name = 'John';
    }
    

    我们将每个控制器功能分配给$scope.someScopeVar,然后我们必须用新控制器编译一个新元素并替换旧的。

    我不相信 Angular 有能力像这样即时更新控制器。可能是一个新功能的好主意。

    FIDDLE


    另一个选择是使用 mixin 模式来更新主范围。你没有得到一个新的闪亮的范围,但它可能适用于你的目的。

    mainCtrl = function($scope, $compile, $element) {
        angular.extend($scope, ctrl1());
        $scope.changeCtrl = function(id) {
             angular.extend($scope, id === 1 ? ctrl1() : ctrl2());
        }
    }
    
    var ctrl1 = function() { 
      var obj = {};
      obj.name = 'World';
      return obj;
    }
    
    var ctrl2 = function() {      
      var obj = {};
      obj.name = 'John';
      return obj;
    }
    

    FIDDLE

    【讨论】:

      猜你喜欢
      • 2017-02-02
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2017-06-06
      • 2016-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多