重用ng-controller作为单例

时间:2014-11-25 10:31:52

标签: javascript angularjs

我知道ng-controller创建了一个新的控制器实例。我怎么能在模板的不同位置重用控制器并保持相同的模型。

我试着自己找出来,但我是AngularJs的新手,有点迷失......

请参阅我在Plunker中的示例:http://plnkr.co/edit/VGLEcdlY4IaAJmJPWhQ7?p=preview

HTML

<body ng-app="app">
    <div ng-controller="test">
        <label ng-click="test()">Test: {{ name }}</label><br/>
        <input type="text" ng-model="name" />
    </div>
    <p>Here some other ng-controller...</p>
    <div ng-controller="test">
        <label ng-click="test()">Test: {{ name }}</label><br/>
        <input type="text" ng-model="name" />
    </div>
</body>

的js

angular
.module('app', [])
.controller('test', function($scope) {
    $scope.name = 'hello world';
    $scope.test = function(){ alert('alert'); };
})

2个字段没有连接到相同的模型/范围,如何使这个单例和两个输入具有相同的模型。

4 个答案:

答案 0 :(得分:3)

我也有类似的情况,我认为你唯一能做的就是使用服务。

angular
.module('app', [])
.controller('test', function($scope, singleton) {
    $scope.name = singleton.getField();


}).service('singleton', function(){
  var field = {value : 'hello world'};


  var getField = function(){
    return field;
  }

  return {
    getField : getField
  };

});

这里我使用'field'作为对象,因为在这种情况下,你将链接到两个控制器中的同一个对象。

http://plnkr.co/edit/8yXY2qsIqcBtTqZDUxSa?p=preview

答案 1 :(得分:0)

到目前为止,最简单的方法是将ng-controller属性移动到父元素:

<body ng-app="app" ng-controller="test">
    <div>
        <label ng-click="test()">Test: {{ name }}</label><br/>
        <input type="text" ng-model="name" />
    </div>
    <p>Here some other ng-controller...</p>
    <div>
        <label ng-click="test()">Test: {{ name }}</label><br/>
        <input type="text" ng-model="name" />
    </div>
</body>

Updated Plunker

答案 2 :(得分:0)

如果我想使用控制器作为单身人士,我会做一些这样的事情(这对我来说是角度1.4.3)

(function (app) {
    var AbstractController = app.controllers.AbstractController;
    MessageBoxController.static = {
        options: AbstractController.static.createOptions([
            '$ionicSideMenuDelegate',
            MessageBoxController
        ]),
        pluginFolderName: 'message_box',
        hooks: [
            {hook: 'leftMenu', template: 'message_list.html'},
            {hook: 'topBarLeft', template: 'main.html'}
        ]
    };
    var instance;
    function MessageBoxController() {
        if(instance){
            return instance;
        }
        instance = this;
        var mp = this;
        mp.messagesNb = 0;
        mp.test = 'blabla';
        extend(mp, new AbstractController());
        function _init(params) {
            mp._parentInit(params, MessageBoxController.static.options);
            mp.init();
        }
        mp.init = function () {
            mp.showMsgButton = false;
            mp.toggleLeftMenu = mp.toggleLeftMenu;
            mp.messages = {};
            mp.getMessageCSSClass = mp.getMessageCSSClass;
            mp.clearMsg = mp.clearMsg;
            mp.registerMessageWatching();
        };
        mp.registerMessageWatching = function () {
            mp.unregisterWatchintInterval('MessageBoxController');
            var interval = setInterval(mp.checkMessages, 1000);
            mp.registerWatchingInterval('MessageBoxController', interval);
        };
        mp.checkMessages = function () {
            var messages = mp.getAllMsgs();
            mp.messages = messages;
            var messagesCount = messages.length;
            if (mp.messagesNb === messagesCount) {
                return;
            }
            if (messagesCount > 0) {
                mp.$scope.$apply(function () {
                    mp.showMsgButton = true;
                });
            } else {
                mp.$scope.$apply(function () {
                    mp.showMsgButton = false;
                });
            }
            mp.messagesNb = messagesCount;
        };
        mp.toggleLeftMenu = function () {
            mp.$rootScope.$root.leftMenu = !mp.$rootScope.$root.leftMenu;
            if(mp.$rootScope.$root.leftMenu){
                mp.$rootScope.buff.title = mp.$rootScope.$root.title;
                mp.$rootScope.$root.title = app.l('Messages');
            }else{
                mp.$rootScope.$root.title = mp.$rootScope.buff.title;
            }
        };
        mp.getMessageCSSClass = function(type){
            switch(type){
                case app.messagesTypes.inform:
                    return 'confirm_msg';
                    break;
                case app.messagesTypes.error:
                    return 'error';
                    break;
                case app.messagesTypes.warning:
                    return 'warning';
                    break;
            }
        };
        mp.clearMsg = function(key){
           mp.messages.splice(key, 1);
           mp.messagesNb--;
           if(mp.messagesNb < 1){
               mp.$rootScope.$root.leftMenu = false;
               mp.$rootScope.$root.title = mp.$rootScope.buff.title;
           }
        };
        _init(arguments);
    }
    app.controllers.MessageBoxController = MessageBoxController;
})(deliveryManagerGlobal);

在模板中写这样的

<div ng-controller="MessageBoxController as msgBox" class="msg_box">
    <div class="card" ng-repeat="(key, message) in msgBox.messages">
        <div class="item item-text-wrap" ng-class="msgBox.getMessageCSSClass(message.type)">
            {{message.context}}
        </div>
        <div class="close ion-android-close" ng-click="msgBox.clearMsg(key)"></div>
    </div>
</div>

如果你这样写,你不要使用$ scope(angular是为每个ng-controller新范围创建的),你可以使用singelton。 你可以添加新的dom元素与相同的ng-controller =&#34; MessageBoxController as msgBox&#34;它将使用您的prev实例。目前我还没有看到我的应用结构中的附带错误。我使用了dinamic hooks managmet所以我需要单身,这对我来说很好

答案 3 :(得分:0)

仔细考虑你在这里做了什么。控制器不应该保持状态。它应该是可重复的和无国籍的。如果你想坚持状态我建议你使用服务。服务是单身设计。