When calling a $mdDialog and then calling one more $mdDialog right after the first one - then this error appears 3 times in a row.
No I do not use $scope.apply() or $scope.$digest() anywhere in my code.
$scope.$$phase is null at the time of the error
The full code is too big to post here, and the error happens inside the $mdDialog minified functions.
Anyway this is where we call $mdDialog:
$scope.$on('openDialog', function(event, data){
$mdDialog
// Open the dialog
.show({
template: require('./confirmDialog.html'),
parent: angular.element(document.body),
controller: function($scope) {
var vm = this;
vm.header = data.header;
vm.question = data.question;
vm.cancel = function() {
$mdDialog.cancel();
}
vm.yes = function() {
$mdDialog.hide('yes');
}
vm.no = function() {
$mdDialog.hide('no');
}
},
controllerAs: 'vm',
clickOutsideToClose:true
})
// React to answer
.then(function(modalActionResult){
console.log("scope phase", $scope.$$phase);
$scope.modalActions({'performAction': modalActionResult, 'type': data.type});
})
// Catch any errors
.catch(function(){
})
// Close and kill listeners?
.finally(function() {
});
});
Related
$mdDialog.show accepts an onComplete function which is triggered once the show action is complete. See https://material.angularjs.org/latest/api/service/$mdDialog#show.
How can I get that same onComplete functionality but from within the dialogs controller (not the parent controller calling the dialog)?
From the parent controller:
var onCompleteDeferred = $q.defer();
$mdDialog.show({
templateUrl: '/app/dialog.html',
controller: 'dialogController',
onComplete: onCompleteDeferred.resolve,
locals: {
loadingPromise: function () {
return onCompleteDeferred.promise;
},
success: function() {}
}
})
Within the dialog's controller:
myApp.controllers.controller("dialogController", [
"success",
"loadingPromise",
function (
success,
loadingPromise
){
loadingPromise().then(function() {
//everything in here is guaranteed to be ran AFTER the dialog has been opened
});
}
)
I have a little Angularjs application making use of $mdDialog to pop up a html page that has one text input on it
I want to be able to return the value the user types into the input back to the parent scope. I'm unsure how to do this.
This is what I have so far
$scope.showNewTeamDialog = function () {
$mdDialog.show({
controller: NewTeamDialogController,
templateUrl: 'NewTeam.html',
locals: { newTeamName: $scope.newTeamName },
parent: angular.element(document.body)
})
};
function NewTeamDialogController($scope, $mdDialog, newTeamName) {
$scope.closeDialog = function(newTeamName) {
// before closing I want to set $scope.newTeamName to whatever the user typed in the text on the dialog pop up
$mdDialog.hide();
}
}
The cleanest solution that I use is sending the data back when $destroy is fired. This is clean because it handles all cases for why the dialog is closing, ie when there's a click outside or the escape key is pressed or $mdDialog.hide() is called.
app.controller('CallerController', ['$scope', '$mdDialog',
function($scope, $mdDialog) {
$scope.some_event_listener = function(e) {
$mdDialog.show({
parent: angular.element(document.body),
controller: SomeDialogController,
templateUrl: 'some_dialog.html',
locals: {
on_complete: function(data_from_dialog_controller) {
console.log(data_from_dialog_controller);
}
}
});
};
}]);
app.controller('SomeDialogController', ['$scope', '$mdDialog', 'on_complete',
function($scope, $mdDialog, on_complete) {
$scope.$on('$destroy', function() {
on_complete($scope.some_input_model);
});
}]);
While this wouldn't be right before the dialog closed, I would probably do this using the .then part of the dialog.show promise. Here is a codepen with using one of the ngMaterial examples to modify a variable on close: https://codepen.io/mckenzielong/pen/veBrgE. Basically, something like this:
$scope.showNewTeamDialog = function () {
$mdDialog.show({
controller: NewTeamDialogController,
templateUrl: 'NewTeam.html',
locals: { newTeamName: $scope.newTeamName },
parent: angular.element(document.body)
})
.then((newTeamName) => {
$scope.newTeamName = newTeamName;
})
};
function NewTeamDialogController($scope, $mdDialog, newTeamName) {
$scope.closeDialog = function(newTeamName) {
$mdDialog.hide(newTeamName);
}
}
Alternatively you could do something a little more ugly, and share the scope like this: https://codepen.io/mckenzielong/pen/zEOaRe. One downside to this is your code will become confusing very quickly. Something like this:
$scope.showNewTeamDialog = function () {
$mdDialog.show({
controller: NewTeamDialogController,
templateUrl: 'NewTeam.html',
scope: $scope.newTeamName,
parent: angular.element(document.body)
})
.then(() => {
})
};
function NewTeamDialogController($scope, $mdDialog) {
$scope.closeDialog = function(newTeamName) {
$scope.newTeamName = newTeamName
$mdDialog.hide();
}
}
I am using angular-modal-service library. My logic is : when the modal is open it runs a function from SomeService, and $rootScope.$broadcast from SomeService to modal controller that way I can send resource from service to my modal controller. However, it doesn't fire. Please help me to figure out what I have missed. Thank you.
**Service: **
angular.module('ng-laravel').service('SomeService', function($rootScope, Restangular, CacheFactory, $http) {
this.testFunction = function() {
console.log("from service");
$rootScope.$broadcast('event', {success:'success'});
};
}
**Controller: **
$scope.show = function(customer_id) {
ModalService.showModal({
templateUrl: 'modal.html',
inputs: {
customer_id: customer_id
},
scope: $scope,
controller: function($scope, close) {
$scope.customer_id = customer_id;
$scope.close = function(result) {
close(result, 500); // close, but give 500ms for bootstrap to animate
};
$scope.$on('event', function(event, data){
alert('yes');
console.log('from modal controller');
});
}
}).then(function(modal) {
SomeService.testFunction(customer_id, tour_id);
modal.element.modal();
modal.close.then(function(result) {
$scope.message = "You said " + result;
});
});
};
After switching the function it works, but...
how could i pass data in to modal? like ui-bs-modal, they have resolve.
You're being broadcasting event before events from modal controller are binding. So before broadcasting event make sure that event listeners are registered(meaning modal controller has been loaded). So call SomeService.testFunction(); after showModal method.
$scope.show = function(customer_id) {
ModalService.showModal({
templateUrl: 'modal.html',
inputs: {
customer_id: customer_id
},
scope: $scope,
controller: function($scope, close) {
//code as is
//listeners will get register from here.
}
})
.then(function(modal) {
SomeService.testFunction(); //broadcasting event
}).catch(function(error) {
// error contains a detailed error message.
console.log(error);
});
};
You are broadcasting the event, before the modal controller is instantiated or created, as service function is called before ModalService.showModal. Try changing the order. That should work fine.
Inside $scope.show try this order
$scope.show = function(){
ModalService.showModal({
....
// Listen for broadcast event
});
SomeService.testFunction();
}
Bear with me - I'm an AngularJS newb.
I have a form that I want to be available from anywhere in my app, and I'm trying to figure out how to code that. My current attempt is to put the modal into a service, like this:
.service('NewObjectService', function() {
var svc = this;
svc.showModal = function() {
$ionicModal.fromTemplateUrl('template.html', {
scope: null, // what should I do here?
animation: 'slide-in-up'
}).then(function(modal) {
svc.modal = modal;
modal.show();
});
}
})
.controller('NewObjectController', function() {
$scope.$on('$ionicView.enter', function() {
console.log('NewObjectController');
// setup new object
})
})
Then from anywhere in my app, I can call NewObjectService.showModal() and the modal pops up. That part is working.
The trouble I'm running into is that I can't get my controller to fire, so the initialization never gets called and my new object is null.
It seems like I should actually be calling the modal from within NewObjectController to setup scope, but I tried that and I couldn't figure out how to call that controller from within other controllers - hence the service.
I know I'm just doing something fundamentally wrong, but I'm not sure what it is. Any help?
Update: I also just tried calling one controller from another using a root scope broadcast:
.controller('MainCtrl', function() {
this.showModal = function() {
$rootScope.$broadcast('new_object:show_modal');
}
})
.controller('NewObjectCtrl', function() {
$rootScope.$on('new_object:show_modal', function() {
// show modal
})
})
The problem I'm running into there is that NewObjectCtrl hasn't been invoked at the time MainCtrl runs, so it doesn't catch the broadcast event.
When you declare a service you need to return itself in the Angular declaration ie var svc = {}; return svc; Call svc.showModal from any controller after you've injected the service and pass in the scope. Call the controller from another controller by using $rootScope.$on (receiver) and $rootScope.$emit (from)
.service('NewObjectService', function($ionicModal) {
var svc = {};
svc.showModal = function(_scope) {
$ionicModal.fromTemplateUrl('template.html', {
scope: _scope, // passing in scope from controller
animation: 'slide-in-up'
}).then(function(modal) {
svc.modal = modal;
modal.show();
});
}
return svc;
})
.controller('NewObjectController', function($scope, $rootScope, NewObjectService) {
// fires off when $rootScope.$emit('ShowModal') is called anywhere
$rootScope.$on('ShowModal', function(data) {
NewObjectService.showModal(data._scope);
});
})
.controller('OtherController', function($scope, $rootScope) {
$scope.contactOtherController = function() {
// contact the other controller from this controller
$rootScope.$emit("ShowModal", {scope: $scope});
}
})
I'm new to angular, trying to use angular material to create a popup dialog. I'm confused with the promise and $scope here. If I click the dialog button, console will show 'created' and then no window will popup.
But if I change it to .then(createFolder, ..), function createFolder(){...}, everything is ok.
$scope.createFolder = function(ev) {
$mdDialog.show({
controller: dialogController,
templateUrl: 'dialog_new_folder.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
})
.then($scope.createFolder, $scope.cancelDialog);
};
$scope.createFolder = function() {
console.log('created')
}
$scope.cancelDialog = function() {
console.log('cancelled')
}
function dialogController($scope, $mdDialog) {
$scope.folderName = '';
$scope.hide = function() {
$mdDialog.hide();
}
$scope.cancel = function() {
$mdDialog.cancel();
}
}
You're using $scope.createFolder for both the function to call when the dialog is closed successfully, and for the function to show the dialog. Your second declaration is overwriting your first. Rename one of them.