简体   繁体   English

在运行时动态分配ng-controller

[英]Dynamically assign ng-controller on runtime

I have a situation where I need to dynamically change the controller, so that the scope variables are influenced accordingly. 我有一种情况需要动态更改控制器,以便相应地影响范围变量。 General structure: 一般结构:

<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>

I saw here that it can be done within an ng-repeat . 我在这里看到它可以在ng-repeat Can it be done outside of it? 可以在它之外完成吗? In other words, can I tell angular to read it as a variable rather than a string literal? 换句话说,我可以告诉角度将其读作变量而不是字符串文字吗?

As discussed in the comments, angular has a really powerful feature/library for handling these scenarios - ui-router (with its powerful wiki ) . 正如评论中所讨论的, angular有一个非常强大的功能/库来处理这些场景 - ui-router (带有强大的wiki

The ui-router is an answer to need to develop functional pieces - states , rather then think in view/url (cite from a home page) : ui-router是开发功能部件的必要条件 - 状态 ,而不是在视图/ url中思考(从主页引用)

AngularUI Router is a routing framework for AngularJS, which allows you to organize the parts of your interface into a state machine . AngularUI Router是AngularJS的路由框架,它允许您将接口的各个部分组织到状态机中 Unlike the $route service in the Angular ngRoute module, which is organized around URL routes, UI-Router is organized around states , which may optionally have routes, as well as other behavior, attached. 与Angular ngRoute模块中的$ route服务不同,Angular ngRoute模块是围绕URL路由组织的, UI-Router是围绕状态组织的,可以选择附加路由以及其他行为。

There are some very interesting blog posts: 有一些非常有趣的博客文章:

...The most interesting thing about AngularJS's new router, isn't the router itself, but the state manager that comes with it. ...关于AngularJS新路由器最有趣的事情不是路由器本身,而是随之而来的状态管理器。 Instead of targeting a controller/view to render for a given url, you target a state. 您可以定位一个州,而不是将控制器/视图定位为呈现给定的网址。 States are managed in a heirarchy providing inheritance of parent states and complex composition of page components, all the while remaining declarative in nature... 国家在层次结构中进行管理,提供父状态的继承和页面组件的复杂组合,同时保持声明的性质......

... ui-router fully embraces the state-machine nature of a routing system. ... ui-router完全包含路由系统的状态机特性。 It allows you to define states , and transition your application to those states. 它允许您定义状态 ,并将应用程序转换为这些状态。 The real win is that it allows you to decouple nested states , and do some very complicated layouts in an elegant way. 真正的胜利是它允许你解耦嵌套状态 ,并以优雅的方式做一些非常复杂的布局。

Exactly the point we need - decouple child states... dynamically change the controller in fact ... could be by url change or just a state change (one sibling child instead of other without url change) 正是我们需要的点 - 解耦子状态...... 实际上动态改变控制器 ......可能是通过URL更改或只是状态更改(一个兄弟孩子而不是其他没有网址更改)

You need to think about your routing a bit differently, but once you get your head around the state-based approach, I think you will like it... 你需要以不同的方式考虑你的路由,但是一旦你了解了基于状态的方法,我想你会喜欢它......

Finally, there are few links, which I would mark as the saint grail of ui-router 最后,有几个链接,我将其标记为ui-router的圣杯

  • Sample application . 样品申请 In action we can see, how the ui-router state machine does work. 在行动中我们可以看到,ui-router状态机如何工作。 We can load list as a parent state , then we can select row items, which do represent their own child state ... while parent is not reloading ( here I tried to explain it in more details) 我们可以将列表作为父状态加载,然后我们可以选择行项,它们代表他们自己的子状态 ......而父代没有重新加载这里我试着更详细地解释它)

  • state.js - the essential piece of code of the sample application. state.js - 示例应用程序的基本代码段。 This is one of the best documented code snippets I've seen... Spent some time to go through and this will give you the 80% percent of answers: How ui-Router is working 这是我见过的最好的文档代码片段之一...花了一些时间来完成,这将给你80%的答案: ui-Router如何工作

From my experience, this is really suitable for small apps as well as for large scale systems... love it... 根据我的经验,这非常适合小型应用程序以及大型系统......喜欢它......

The way this works for ngRepeat is different. 这对ngRepeat工作方式是不同的。 It works because it compiles each repetition, which is what you need to do here. 它起作用,因为它编译每个重复,这是你需要在这里做的。

For example: 例如:

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';
}

We assign each controller function to $scope.someScopeVar , then we must compile a new element with the new controller and replace the old one. 我们将每个控制器函数分配给$scope.someScopeVar ,然后我们必须用新控制器编译一个新元素并替换旧元素。

I don't believe angular has the capability to update a controller on the fly like that. 我不相信角度有能力像这样快速更新控制器。 Might be a good idea for a new feature. 对于新功能可能是一个好主意。

FIDDLE 小提琴


Another option would be to use the mixin pattern to update the main scope. 另一种选择是使用mixin模式更新主范围。 You don't get a new shiny scope but it may work for your purposes. 您没有获得新的闪亮范围,但它可能适用于您的目的。

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 小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM