I want to ask if the parent scope destroy, does the child scope will also be destroy?
I ask this question is because i'm using the ngdialog to create some modal dialogs.
There are 2 dialogs, A -> B, we can open dialog A from a web page, and dialog A is parent of dialog B, click button on A to open B.
I want to open dialog B and close A(the parent of B) at the same time, and the data in scope B are all missing. So i think maybe it is caused by this. can anyone help me to get better understanding on this?
dialogACtrl:
$scope.selectServer = function (serverType) {
$scope.serverType = serverType;
$scope.closeThisDialog('close'); //close current dialog
var newScope = $scope.$new(true);
var modalInstance;
modalInstance = ngDialog.openConfirm({
template: 'servers/templates/dialog-b.tpl.html',
scope: newScope,
controller: 'dialogBCtrl',
resolve: {
serverData: function () {
return null;
},
delegate: callbackWrapper
}
});
siteScopeModalInstance.result.then(callback);
ngDialog source:
open: function (opts) {
...
scopes[dialogID] = scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
performCloseDialog: function ($dialog, value) {
...
scope.$destroy();
When a parent scope is destroyed, it basically cascade destroy it's child scopes tree.
I suspect this has nothing to do with parent/child scopes
Each instance of the dialog will initialize it's own controller instance.
This means that when you open the second dialog, it has it's own scope that is different than the scope in the first dialog.
Any data you need to pass from one to the other would need to be either done with a resolve or by using a service to share data across controllers.
Without any code posted in your question it is hard to help further
Related
I created a scope and controller dynamically from my code (usually from a provider) as given below
var controllerFn = function ($scope) {
/* scope functions and variables */
$scope.$on('custom_ng_event', function (evt) {
console.log('Custom evt listened in dynamic scope');
});
$scope.$on('$destroy', function () {
console.log('Dynamically created scope destroyed');
});
}
var $scope = $rootScope.$new();
var ctrlInstance = $controller(controllerFn, {$scope: $scope});
I want to remove the scope and de-register the controller at a certain point. I thought that $scope.$destroy() would do the task, but I think I'm missing something as it is not giving the expected result. Like, any broadcast to the $rootScope is still being reflected in the dynamically created scope listener.
Please help me to understand what I have done wrong.
Additional Info:
I preference is to have my dynamically created scope to be a child scope of root scope (directly) because it is meant to be used for the whole application (similar to that of a modal).
Thanks in advance
Balu
I have a module called LegalModule, there are three components that subscribe to the same module, basically:
Both components have their own folder and each have an index.js file where they bootstrap like:
angular.module('LegalModule')
.component('person', require('person.component.js')
.controller('PersonController', require('person.controller.js');
and another file like
var component = {
templateUrl: 'person-tamplate.html',
controller: 'PersonController',
bindings: {info: '<'}
}
module.exports = component;
Then in that controller i have something like :
var controller = ['PersonRepository','$stateParams', function(PersonRepository, $stateParams)
{
var vm = this;
//other code
function Save(){
//code that saved
}
function onSuccess(){
//Let another component know this happened and call its refresh function.
}
}];
Other component / controller
angular.module('LegalModule')
.component('buildings', require('buildings.component.js')
.controller('BuildingController', require('buildings.controller.js');
and the component
var component = {
templateUrl: 'building-template.html'
controller: 'BuildingController'
}
Controller
var controller = ['BuildingReader',function(BuildingReader){
function refreshBuildings(){
//this needs to be called on success of the save of the Person Repository
}
}];
On the main tamplate:
<div class="LegalFacilities">
<person></person>
<buildings></buildings>
</div>
So i am new to components and i am not sure how to make in a way that when something is saved in the person controller, on it's success, that it can trigger the refresh function in the building controller to fire.
I really do not want to use $scope or anything like that , there is gotta be a cleaner way?. (not sure but i would appreciate any inputs).
Since you have two components that are not on the same DOM element, your methods of communicating between them are more limited. You still have several ways that you can do it:
onSuccess() emits an event on the $rootScope and all interested controllers listen for that event (just make sure to unsubscribe to the event on $destroy).
Create one or more services that contain the all the non-UI shared application state. All controllers that need access to state inject the service that contains that state. And controllers can also $watch a variable on the service to be notified when something changes and something needs to be refreshed.
Pass state around using the parent scope. Ie- each child scope declares a scope variable that is bound to the same variable in the parent scope. And if the state changes in one of the child scopes, the $digest cycle will ensure that the state is propagated to the other child scope.
In general, my preference is #2. The reason is that this keeps a clear separation between application state and UI state. And it becomes very easy to ensure that all parts of your application can share bits that they need to.
In your case, since you need to notify that an action happened, you can trigger this through changing a successHash number (an opaque number that just gets incremented on every save such that all watchers are notified).
Edit: a very simple example of sharing state using services.
angular.module('mymod').service('myService', function() {
this.val = 9;
});
angular.module('mymod').directive('dir1', function(myService, scope) {
scope.doSomething().then(res => myService.val = res);
});
angular.module('mymod').directive('dir2', function(myService, scope) {
scope.$watch(() => myService.val, () => console.log(`It happened! ${myService.val});
});
I have a main controller for my profile edit page, from where users can add their education, in a modal window. The modal has it's own controller. The user can add as many education items they want and they can modify the existing ones.
Now for my issue. I want the modal controller to take care of both adding a new item and updating an existing one. The difference is that on update, the controller should receive a fully populated education object, which it should update. I don't know how to pass this object from the main controller to the modal controller. I've seen some ways of passing data between controllers via services, but that seems too much of a hassle, and it doesn't make sense to me to use a service in this particular case.
My main controller creates modals like so:
vm.openEducation = function(){
$modal.open({
templateUrl: "some.html",
controller: "SomeController",
controllerAs: "vm",
size: 'lg'
}).result.then(function (education) {
vm.educations.push(education);
});
}
And the child controller (which currently only supports insert, hence the empty init of vm.education):
function SomeController($scope){
var vm = this;
vm.education = {}; // or get from parent controller
vm.save = function () {
$scope.$close(vm.education);
};
vm.close = function () {
$scope.$dismiss();
}
return vm;
}
You can use $rootScope.$broadcast to send data from the modal and then $scope.$on to receive that data anywhere else.
For example:
// in your modal
$rootScope.$broadcast('education:updated', yourDataObj)
// in your controller
$scope.$on('education:updated', function(e, data) {
console.log(data)
})
Note that the $broadcast will be picked up by anything that's listening for it, so if you have multiple controller instances you will get multiple console.log messages
I have a list of groups in my application. when i click on the group, a modal window opens using the modalController with the group related data. form this modal user can make changes to the group. now when i make any change in the group and save it. the changes reflect in the list in the background but not in the modal box.
What i can do here?
:(( suplicate::((
Modals in anuglar , regularily has their own instance and controller , they dont get their parrent scope(scope of your view)
So you have to Send this scope(scope of your view) with a resolve property like this :
There should be a resolve property in your modal instance , where you can resolve anything you want ;
yourApp.controller('yourViewController',function($scope,...){
$scope.openModal = function (size) {
var modalInstances = $modal.open({
templateUrl: 'yourModalTemplateURL.html',
controller: 'YourModalController',
size: "YourModalSize",
resolve:{
info :function(){
// you want to see your scope later in your modal
// so you have to resolve it and sent it via this property
return $scope;
}
}
});
};
})
And in your ModalController you can inject that info
app.controller('YourModalController',function($scope,info){
console.log(info); // will log the scope of your controller
});
I have a scenario, i which I have a share button, I have a container controller, called metaCtrl, which is on the html tag.
And also inner controllers.
I have a share button, that calls the model.share() function on click.
code:
app.controller('metaCtrl', function($scope){
$scope.model = {};
$scope.model.share = function(){
$location.path('/share').search({'share' : '1'});
}
});
The controller of the share page it self:
app.controller('shareCtrl', function($scope)){
$scope.layout.shareVisible = $location.path().share == 1 ? true : false;
$scope.model.share = function(){
$scope.layout.shareVisible = $scope.layout.shareVisible ? false : true;
var shareUrlValue = $scope.layout.shareVisible ? 1 : null;
$location.search('share', shareUrlValue);
}
});
The idea is to use the same HTML pattern in the entire application, but only to toggle the share section on the share page(if the user is already there), and to send the user to the share view if he is not currently there.
The problem is that after I go to the sahre page, and then return to the other page, the function share() has a referance to the function in the shareCtrl, rather then to the metaCtrl.
I'm not sure there's enough information here, but I'll take a shot at it (I can't comment because I don't have enough rep). Notice that your shareCtrl is not creating a new model object, you're just assigning $scope.model.share = func....
That assignment is overriding the function in the parent controller because Angular is going up the scope chain to find the model object.
See this Plunker:
http://plnkr.co/edit/yv5rrpdlkniZdg94T4Lf
Notice with $scope.model = {} commented out in shareCtrl, the value of both fields is "shareCtrl". But, if you uncomment that line, then $scope.model is within the shareCtrl scope so Angular doesn't go up the scope chain looking.