I pass the link of this example, I have a variable called "greeting" that changes its value in a modal window but does not bind. Do not share scope?
http://jsfiddle.net/Bibidesign/Lodkh4jy/7/
var myApp = angular.module('myApp',['ui.bootstrap']);
myApp.controller('GreetingController', ['$scope', '$modal', function($scope,$modal) {
$scope.greeting = 'Hello!';
$scope.changeValues = function() {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
backdrop: 'static',
scope: $scope,
controller: function($scope, $modalInstance) {
$scope.greeting = "Welcome";
$scope.cancel = function(){
modalInstance.close();
}
$scope.ok = function(){
modalInstance.close();
}
}
});
};
}]);
You are partially there. We just need to set up passing the variables between the GreetingController and the Modal controller. We will use the resolve property on the object passed into $modal.open() to pass a value to the modal controller, and than when we close the modal, we will pass back the new value through those the results object. We are also removing scope: $scope, because the controller declaration is overriding that scope copy, and we want to keep these scopes separate. Example to follow.
This answer has a more thorough explanation of what is happening with the resolve, but it is essentially just a simplified way to resolve promises and guarantee data is in the controller before initializing the modal.
myApp.controller('GreetingController', ['$scope', '$modal', function($scope,$modal) {
$scope.greeting = 'Hello!';
// this will handle everything modal
$scope.changeValues = function() {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
backdrop: 'static',
// resolve is an object with all the objects we will pass to the controller
// I'm adding more than just greeting for examples sake
resolve: {
greeting: function () {
return $scope.greeting;
},
testData: function () {
return "This is some random test data";
}
}
// on the controller parameters, we add the properties we are resolving
controller: function($scope, $modalInstance, greeting, testData) {
// the greeting variable passed in through resolve
console.log('greeting', greeting); // expected output: greeting Hello!
// the testData passed in through resolve
console.log('testData', testData); // expected output: testData This is some random test data
// this will be the greeting you are able to access on the modal
// we can set this to the value from the resolve or a new value like below
$scope.greeting = "Welcome";
//$scope.greeting = greeting // this will set the modal to the value passed in from the resolve
// NOTE*** I changed this call to dismiss()
$scope.cancel = function(){
modalInstance.dismiss();
}
$scope.ok = function(){
// what ever we pass in to close will be accessible in the result below
// we are passing in the new greeting - 'Welcome'
modalInstance.close($scope.greeting);
}
}
});
// this is the majority of the new code
modalInstance.result.then(function(okReturnObject){
// this okReturnObject will be whatever you pass in to modalInstance.close()
console.log('return', okReturnObject); // expectedOutput: return Welcome
// this is where we are setting the original value to the new value from the modal
$scope.greeting = okReturnObject;
},function(){
// will be run after modalInstance.dismiss()
console.log("Modal Closed");
});
};
}]);
You can't url refer the text/ng-template as the templateUrl. Instead, add the html form in a separate html file and refer to that in the modal declaration.
Here's a working plunker https://plnkr.co/edit/lMZK0uGNsEmRjAN7teVZ?p=preview
Related
I'm trying to get modals woking with angular bootstrap. I can launch the modal just fine, but I'm having some scope issues dismissing the modal.
When I launch the modal, I can specify a controller that I can call functions from, which works, but it seems to be a copy of the controller without a $parent and without any controller-local variables.
I need access to the return value of $uibModal.open() in order to close the modal, so I'm trying to store it in var modalInstance, which works fine when I'm within the scope of the controller, but the copy of the controller passed into the $uibModal service doesn't have the local variable modalInstance set.
I can get around this by storing the return object in the $rootScope, but that seems like a bad idea. Am I wrong? What's the best way to get access to modalInstance from the click handler passed into the $uibModal service? Can I avoid using the $rootScope?
var app = angular.module('main', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope, $rootScope, $uibModal) {
var modalInstance;
$scope.launch = function() {
console.log('launch');
modalInstance = $uibModal.open({
template: '<div>Modal Content - <a ng-click="close()">Close</a></div>',
controller: 'MainCtrl',
});
// Wouldn't need to do this if I could access modalInstance in close handler
$rootScope.modalInstance = modalInstance;
}
$scope.close = function () {
console.log('close');
console.log(modalInstance);
// Works, but should I be using $rootScope like this?
//$rootScope.modalInstance.close();
// Doesn't work, modalInstance is undefined
modalInstance.close();
}
});
Angular instantiates a new instance of a controller whenever it is used, and it is the same for modal. So when you specify controller: 'MainCtrl' you're telling angular you want to instantiate one of those for your modal, which is rarely what you want.
Instead you should create a separate controller for the dialog, which can return values on closing using the $uibModalInstance service.
var app = angular.module('main', ['ui.bootstrap']);
app.controller('MainCtrl', function($scope, $rootScope, $uibModal) {
var modalInstance;
$scope.launch = function() {
console.log('launch');
modalInstance = $uibModal.open({
template: '<div>Modal Content - <a ng-click="close()">Close</a></div>',
controller: 'DialogCtrl',
});
....
}
});
app.controller('DialogCtrl', function($scope, $uibModalInstance) {
$scope.theThingIWantToSave = [];
$scope.cancel = function () {
$uibModalInstance.close($scope.theThingIWantToSave);
};
});
JS Code,
var mod= $modal.open({
animation: true,
templateUrl: $scope.url,
controller: function($scope, $modalInstance,custObj) {
alert(custObj); /*************Line 1**************************/
$scope.save = function() {
$modalInstance.close();
};
$scope.cancel = function(){
$modalInstance.dismiss('cancel');
};
},
resolve : {
/************Resolving current scope value to retrieve it in Line 1*******/
custObj: $scope.customer;
}
});
Though I sent $scope.customer object via resolve property, the modal controller is not getting the value. Am I missing anything?
The value of custObj in the resolve-object should be a function returning what you want to inject:
resolve: {
custObj: function(){
return $scope.customer;
}
}
check documentation for $routeProvider resolve
use
locals : {
custObj: $scope.customer;
}
instead of resolve.
I have a little issue by using a customize directive within the template field of UI-Bootstrap modal directive.
My aim is send data to modal via resolve attribute and re-use these resolved parameters inside the controller of my own directive.
var app = angular.module('app', ['ui.bootstrap']);
app.controller('MyCtrl', ['$scope', '$modal', function($scope, $modal) {
$scope.openModal = function () {
var popup = $modal.open({
template: '<my-modal></my-modal>',
resolve : {
mydata : function() {
return 42;
}
}
});
};
}]);
app.controller('ModalController', ['$scope', 'mydata', function($scope, mydata) {
//The error is in this directive controller
$scope.mydata = mydata;
}]);
app.directive('myModal', function() {
return {
restrict: 'E',
templateUrl : 'mymodal.html',
controller : 'ModalController',
replace: true
};
});
Maybe I proceed in the wrong way.
Any suggest to make this code functionnal ?
http://plnkr.co/edit/RND2Jju79aOFlfQGnGN8?p=preview
The resolve parameters are only injected to the controller defined in the $modal.open config parameters, but you want to inject it to the directive controller. That will not work. Imagine you would use the myModal directive somewhere else, there wouldn't be a myData object that could be used.
But i don't realy see, what you need the directive for. You could go much easier this way:
app.controller('MyCtrl', ['$scope', '$modal',
function($scope, $modal) {
$scope.openModal = function() {
var popup = $modal.open({
templateUrl: 'mymodal.html',
controller: 'ModalController',
resolve: {
mydata: function() {
return 42;
}
}
});
};
}
]);
// Here the mydata of your resolves will be injected!
app.controller('ModalController', ['$scope', 'mydata',
function($scope, mydata) {
$scope.mydata = mydata
}
]);
Plunker: http://plnkr.co/edit/bIhiwRjkUFb4oUy9Wn8w?p=preview
you need to provide an Object "mydata". Ensure, that you have a correct implemented factory which provides your myData Object. If you had done that, you can "inject" your myData Object where ever you want to.
yourApp.MyDataFactory = function () {
var myData = {i: "am", an: "object"};
return myData;
}
this would provide an "myData" Object
I'm not sure what you are trying to accomplish with the directive, but if you are trying to provide a generic way to invoke the $model, that you can then use from many places in your app, you may be better off to wrap $model with a service. Than you can then call from other places in your app.
I forked and modified your plunkr to work this way: http://plnkr.co/edit/0CShbYNNWNC9SiuLDVw3?p=preview
app.controller('MyCtrl', ['$scope', 'modalSvc', function($scope, modalSvc) {
var mydata = {
value1: 42
};
$scope.openModal = function () {
modalSvc.open(mydata);
};
}]);
app.factory('modalSvc', ['$modal', function ($modal) {
var open = function (mydata) {
var modalInstance,
modalConfig = {
controller: 'ModalController',
resolve: {
mydata: function () {
return mydata;
}
},
templateUrl: 'mymodal.html'
};
modalInstance = $modal.open(modalConfig);
return modalInstance;
};
return {
open: open
};
}]);
Also, I changed mydata to be an object, rather than '42', as I am sure you will have other data to pass in. the markup was updated accouringly:
<div class="modal-body">
BODY {{mydata.value1}}
</div>
Doing it this way, the resolve property works, and you can get your data.
As for the other answers mentioning you must define mydata, the resolve property passed into $model does this for you, so it can be injected into the modal's controller (ModalController), like you have done.
I'm trying to implement angular UI modal and trying to set few default values before create person screen is opened. Say a new person object like below:
var person = {};
person.name = 'default';
In this function
modalCtrl.open = function(size) {
var person = {};
person.name = 'default';
console.log('person-->' + person);
console.log('person.name-->' + person.name);
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
scope: $scope,
resolve: {
person: function() {
return person;
}
}
});
I can do the same thing in update flow if the object is passed by a called.
My assumption is that I should be able to create a new object and resolve it to display few default values on create screen. Does anyone know why I can't do it? Here is the plunker:
http://plnkr.co/edit/XLrbQpDoV8bx1vktbygx?p=preview
You can resolve it.. just need to add person as a dependency to the modal instance controller
app.controller('ModalInstanceCtrl', ['$scope', '$modalInstance', 'person',
function($scope, $modalInstance, person) {
alert(person.name);
$scope.ok = function() {
$modalInstance.close($scope.person);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
]);
I am new with Angularjs , here is my code,
angular.module('remoteApp')
.controller('ScreensavertabCtrl', function ($scope, $modal, $log, $state,Screensaverchpwservice,
Screensaverchpwgetservice) {
$scope.screensaverData = {
screensaver:{
pwProtect: '1'
}
};
$scope.pwProtectOpen = function () {
if($scope.screensaverData.screensaver.pwProtect == true){
var modalInstance = $modal.open({
templateUrl: 'pwProtectModalContent.html',
controller: pwProtectModalInstanceCtrl
});
}
};
var pwProtectModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.pwProtectCancel = function () {
$modalInstance.dismiss('cancel');
console.log($scope.screensaverData.screensaver.pwProtect)
};
};});
when I enable pwProtectCancel function , I want to get $scope.screensaverData.screensaver.pwProtect
value, I tried to use '$scope.$parent.screensaverData.screensaver.pwProtect' is not work?
I am so confused about that,
anyone ideas?
Change you $modal service call to
var modalInstance = $modal.open({
templateUrl: 'pwProtectModalContent.html',
controller: pwProtectModalInstanceCtrl
scope:$scope
}
and you should get the data no the modal scope.
The documentation mentions about scope option
scope - a scope instance to be used for the modal's content (actually
the $modal service is going to create a child scope of a a provided
scope). Defaults to $rootScope
The default it gets is rootscope.