Angularjs child controller get parent controller scope variable not work? - angularjs

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.

Related

Binding from modal Angularjs

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

How to deal with modal controller outside AngularJs module?

My app uses Angular UI to deal with modals and I think I found a problem, as below:
I have a controller that calls the modal controller:
angular.module('MyApp').controller('MainCtrl', function ($scope, $modal) {
$scope.openModal = function () {
var myModal = $modal.open({
animation: true,
templateUrl: 'ModalContent.html',
controller: ModalCtrl
});
};
});
I also have the modal controller in another file, as a simple function:
function ModalCtrl ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
It's working well, but I think the modal controller have to be inside AngularJs module. The questions are:
Can I do it and keep the modal controller in a separated file?
It's a good practice keep the modal controller outside AngularJs module?
What is the best practice to reuse a modal controller in many pages?
Thanks a lot!
That object you're passing into $modal.open() can be registered as a shared service and the modal controller can be embedded right inside it.
angular.module('myApp').factory('myModalConfig', function() {
return {
animation: true,
templateUrl: 'ModalContent.html',
controller: function($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
};
});
Then just inject that along with the $modal service and pass it.
angular.module('MyApp').controller('MainCtrl', function ($scope, $modal, myModalConfig) {
$scope.openModal = function () {
var myModal = $modal.open(myModalConfig);
};
});
I go further than this myself and wrap the whole thing into a custom modal service factory, so I can just inject one thing and open modals like this: profileModals.editProfile(). But that's beyond the scope of this answer.

Angular bootstrap modal controller scope

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

Working with $emit and $on from child modal to parent angularjs

I have this situation
two files, both in the same app
var app = angular.module('myapp');
file one is the parent and I have:
app.controller("ControllerOne", ['$scope', '$http', '$modal',
function ($scope, $http, $modal) {
$scope.$on('refreshList', function (event, data) {
console.log(data);
});
$scope.openModal = function () {
var modalInstance = $modal.open({
templateUrl: '/SomeFolder/FileWithControllerTwo',
controller: 'ControllerTwo',
size: 'lg',
resolve: {
someParam: function () {
return "param"
}
}
});
}
}]);
file two is the child and I have:
app.controller("ControllerTwo", ['$scope', '$http', 'someParam',
function ($scope, $http, someParam) {
$scope.SaveSomething = function () {
$http.post(url, obj)
.success(function (data) {
$scope.$emit('refreshList', [1,2,3]);
}).error(function () {
});
};
}]);
Assuming that i can open the modal and I can "SaveSomething".
What I need to do to send some data from ControllerTwo to ControllerOne?
I already checked this post Working with $scope.$emit and .$on
but I cant't solve the problem yet.
Obs:
FileOne.js -> I have the ControllerOne (parrent) -> $on
FileTwo.js -> I have the ControllerTwo (child) -> $emit
Yes, I can hit the code inside $http.post.success condition
Assuming you are using angular-ui bootstrap (which has a $model), then the $scope in the model is a childscope of $rootScope.
According to $model documentation you can supply the ControllerOne $scope by using the scope option which will make the modal's $scope a child of whatever you supply. Thus:
var modalInstance = $modal.open({
templateUrl: '/SomeFolder/FileWithControllerTwo',
controller: 'ControllerTwo',
size: 'lg',
scope: $scope,
resolve: {
someParam: function () {
return "param"
}
}
});
Then you could emit to that using $scope.$parent.$emit(...). Strictly speaking, this creates a coupling in that it assumes that the user of the modal listens to the events.
If you don't want to inject your scope, they you could inject $rootScope and emit on that. But that would also send the event to every scope in the application.
This is assuming that you actually want to leave the modal open and send a message back to the parent controller. Otherwise, just use close() or dismiss() methods.

Access scope on specific fuinction in AngularJS

I have a following ambiguity in AngularJS.
I'm using AngularJS ui Modal and provide
controller about this modal. From this controller
I want to access variable from other scope. What is
a angular way to do this? Here is my code:
controllers.controller('ResultCtrl', ['$scope', '$routeParams', '$http', '$q', 'Matches', '$modal',
function ($scope, $routeParams, $http, $q, Matches, $modal) {
/**
* other code
*
* from this scope i can access
* $scope.terms
*/
$scope.mergeTerms = function() {
var ModalInstanceCtrl = function ($scope, $modalInstance) {
/**
* Here I want to access
* $scope.terms as a above
* function
*/
}
}
});
Best regards.
If you are sure, that your ModalInstanceCtrl controller will always be inside your ResultCtrl you could use $scope.$parent.terms, however this might not always be the case.
when using Angular-ui modal, you can pass objects which can be injected into your modal controller:
$scope.modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceCtrl',
resolve: {
terms: function() {
return $scope.terms;
}
}
});
By doing this, you can simply inject terms into controller:
var ModalInstanceCtrl = function ($scope, $modalInstance, terms) {
$scope.terms = terms;
/**
* Here I can access $scope.terms in terms
* which was injected into this controller
*/
}
You'll need to pass it into the Modal Instance Controller so that it can resolve it within it's own scope. Something like this:
var modalInstance = $modal.open({
resolve: {
terms: function () {
return $scope.terms;
}
}
});

Resources