It seems that the code you provided working fine and the problem is somewhere else, probably in cms
controller or in confirm.html
template. I've made a plunker with your factory where you can see it live.
index.html
<div ng-controller="ctrl1">
<button ng-click="msg.confirmSave()">confirm save</button>
<span ng-if="msg.getResponse() !== undefined">Response: {{msg.getResponse()}}</span>
</div>
confirm.html
<h1>{{msg.text}}</h1>
<button ng-click="msg.confirm()">Confirm</button>
<button ng-click="msg.cancel()">Cancel</button>
JavaScript
angular.module('app',['ui.bootstrap']).
controller('cms', ['$scope', 'msg', function($scope, msg){
$scope.msg = msg;
}]).
controller('ctrl1', ['$scope', 'msg', function($scope, msg) {
$scope.msg = msg;
}]).
factory('msg',['$modal', function ($modal) {
// The same code as in the question
}]);
Some tips:
- Use
var factory = {};
instead offactory = {}
in order to declare local variable and not to override globalfactory
occasionally. factory.modal;
andfactory.response;
do not declare relevant properties infactory
object as you expect, but returnundefined
instead, so just remove them, because they are uselessfactory.setText
andfacory.getResponse
are redundant, sincefactory.text
andfactory.response
are public properties offactory
. If you want to make them private to the factory, declare them asvar text;
andvar response;
and change the accessor methods accordingly. It will be also useful to addgetText
to your factory in that case.- If you plan to access
factory.modal
only from you factory, it is better to incapsulate it to your factory (make it private) as described in the previous bullet. - Expose only public API from the factory (don't expose
window
for example)
After applying all tips your factory may look like the following:
factory('msg',['$modal', function ($modal) {
var text = '',
modal,
response;
function window () {
modal = $modal.open({
templateUrl:'confirm.html',
controller:'cms'
});
}
return {
setText: function (_text_) {
text = _text_;
},
getText: function() {
return text;
},
getResponse: function () {
return response;
},
confirm: function () {
modal.close();
response = true;
},
cancel: function () {
modal.close();
response = false;
},
confirmSave: function () {
text = 'save';
window();
},
confirmUpdate: function () {
text = 'update';
window();
},
confirmDelete: function () {
text = 'delete';
window();
}
};
}]);
Here is a plunker.
EDIT:
After you updated the post with controller code everything is clear to me: the real problem is that you use confirmDelete()
synchronously, but it is asynchronous (since returns value in the future, once user clicks confirm or cancel)! To deal with asynch staff angular has a $q
service. In order to use it, you should create deferred object in factory.confirmSave()
, factory.confirmUpdate()
and factory.confirmDelete()
, return it's promise and resolve/reject it in factory.confirm()
and factory.cancel()
. Once promise is resolved or rejected you can fetch the value from factory
or get it directly as argument of relevant callback.
factory
function confirmDelete() {
deferred = $q.defer();
text = this;
window();
return deferred.promise;
}
controller
msg.confirmDelete().then(function(value) {
// Resolved
$scope.response = value;
}, function(value) {
// Rejected
$scope.response = value;
});
Full example see in the following plunker.