How does $mdDialog work with promise and $scope? - angularjs

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.

Related

AngularJS passing data back from mdDialog to parent controller

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

$mdDialog [$rootScope:inprog] $digest already in progress

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

$mdDialog.confirm() with custom templateUrl

I'm using $mdDialog in my application, but would like to use it as a "confirm" dialog instead of normal one. This means, the code flow should not proceed until user clicks on one of the two buttons in confirm dialog. I noticed that $mdDialog.confirm() can be used, but I'm not sure how to use it with custom templateUrl and a corresponding controller as the dialog's content.
Following is what I have written which works fine as far as dialog is concerned, but the code flow doesn't stop after the dialog is opened. It should stop until Ok or Cancel is clicked by the user.
$mdDialog.show({
controller: 'incomingCallDialogController',
templateUrl: 'app/components/others/incomingCallDialog/incomingCallDialog.tpl.html',
locals: {message: message},
parent: angular.element(document.body)
}).then(function (answer) {
console.log("here");
}
Basically it would be something like:
var confirm = $mdDialog.confirm({
controller: 'incomingCallDialogController',
templateUrl: 'app/components/others/incomingCallDialog/incomingCallDialog.tpl.html',
locals: {message: message},
parent: angular.element(document.body)
})
$mdDialog.show(confirm).then(function() {
console.log("here");
}
Here's a codepen.
Angular Js confirm dialog design using Matrial Ui and with icon/images
Screenshot : https://i.stack.imgur.com/rghwX.png
Online demo : https://codepen.io/MuhammadRizwan/pen/aYBKqW?editors=1010
try this
$scope.showTimContent = function (tim) {
$mdDialog.show({
controller: ['$scope', '$mdDialog', 'tim', $scope.ViewTimContentCtrl],
templateUrl: 'wgt/tim/TimContentDialog.html',
locals: {'tim': tim},
clickOutsideToClose: true,
});
};
$scope.ViewTimContentCtrl = function ($scope, $mdDialog, tim) {
$scope.tim = tim;
$scope.hide = function () {
$mdDialog.hide();
};
$scope.cancel = function () {
$mdDialog.cancel();
};
};

When passing scope in angular modal controller, it's not showing second time

I am calling modal popup from my controller. It works fine for the first time but doesn't show the second time.
Here is the code for the show
$scope.showAdvanced = function (ev) {
var scopeVar = $scope;
console.log('$mdDialog');
console.log($mdDialog);
$mdDialog.show({
controller: DialogController,
templateUrl: 'dialog1.tmpl.html',
parent: angular.element(document.body),
scope: $scope,
targetEvent: ev,
clickOutsideToClose: true
}).then(function (result) {
//$scope = $scope.$parent;
console.log($scope);
});
};
Here is my hide function inside DialogController.
$scope.hide = function () {
console.log('hide called');
$mdDialog.hide();
console.log('hide completed');
};
Hide is executing successfully and followed by callback defined in show which prints the current scope.
If I remove scope : $scope and put transclude : true then it is not showing the data in dialog controller though you can show and hide it more than once.
Add preserveScope: true to your modal options. A dialogue removes its scope on closing by default.

Close only one current modal using $modalStack in Ui Bootstrap

I'm using a solution found here: How to close Angular UI Modal from anywhere
to close a UI bootstrap modal that I'm using as an HTTP interceptor to show loading.
However, this solution closes ALL open modals since $modalStack.dismissAll() is being used. How do I remove only the modal that's open with the loading. Here's my code:
app.factory('loadingModal', ['$modal', '$modalStack', function($modal, $modalStack) {
return {
trigger: function(template) {
$modal.open({
windowClass: 'modal fade loading-modal',
templateUrl: '/assets/partials/modals/loadingModal.html',
backdrop: 'static',
controller: function($scope, $modalInstance) {
$scope.ok = function() {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
});
},
close: function(reason) {
$modalStack.dismissAll(reason);
// $modal.close();
}
};
}])
Not totally clear how you are using this in interceptor but you should be able to return the instance from trigger and then use instance.dismiss()
app.factory('loadingModal'.....
return {
trigger: function(template) {
// return this instance
return $modal.open({.....
......
}
Then store instance wherever you intialize trigger() in interceptor
var modal = loadingModal.trigger('tmpl.html');
Then to close
modal.dismiss();
Of course you could store this instance in service and create a method to close it with a service method also

Resources