Reputation: 3170
I understand that ng-controller create a new instance of controller. How could I reused the controller in different place of my template and keep the same model.
I try to find out by myself but I am new in AngularJs and a bit lost...
See my example in 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'); };
})
The 2 fields are not connected to the same model/scope, how can make this singleton and have the same model for both input.
Upvotes: 1
Views: 1771
Reputation: 2583
Think carefully about what you're doing here. A controller shouldn't hold state. It should be repeatable and stateless. If you want to persist state I suggest you use a service. Services are singletons by design.
Upvotes: 0
Reputation: 519
If i whant to use controler as singleton I do some like this(this work for me in angular 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);
And in template write like this
<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>
If you will write like this you do not use $scope( angular is create for every ng-controller new scope) and you can use singelton. sou you can add new dom element with same ng-controller="MessageBoxController as msgBox" and it will use your prev instance. For now I have not see collateral bugs in my app structure. I have use dinamic hooks managmet so I was needed singleton and this work for me good
Upvotes: 0
Reputation: 3111
I had similar case too, and I think the only thing you can do is using service.
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
};
});
Here I used 'field' as an object because in this case you'll have link to the same object in both controllers.
http://plnkr.co/edit/8yXY2qsIqcBtTqZDUxSa?p=preview
Upvotes: 3
Reputation: 67296
By far the most simple way is to move the ng-controller
attribute up to the parent element:
<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>
Upvotes: 0