there i want to apply $mdDialog to the following angular function and I'm using angularjs 1.6.4. $mdDialog should prompt a message to select Yes or no to delete the file. Here is my code
$scope.deleteFile = function (key) {
$scope.documentEventText = "Document Deleted";
FileResourceService.deleteFile('KeyPhotos', key, $state.params.propertyId, $scope.key.id, $scope.getFiles);
}
Open the dialog inside the function as follows,
var confirm = $mdDialog.confirm({
controller: DialogController,
templateUrl: 'dialog1.tmpl.html',
parent: angular.element(document.body),
targetEvent: ev,
})
$mdDialog.show(confirm).then(function() {
$scope.status = 'Confirmed';
}
DEMO
Related
I've recently switched all our modals directives in our app over to Angular-ui-Bootstrap modals. Much better, however running into a new style of modal which closes on mouseleave instead of a cancel click.
this.leaveTag = (tag) => {
TagHover.off();
};
this.hoverTag = (tag) => {
TagHover.display();
};
Above is the view logic that calls functions inside of our TagHover Factory.
Below is the Factory, the TagHover.display works fine like with our other modals, but what I'm trying to do with the leaveTag > TagHover.off is call the modal.close. Not working so far.
My question is how do you call the close functionality within the TagHoverController, or close on the $uibModal from my tagsPanel component -> TagsHover Factory? (Without using $scope or $rootScope events)
I'm not trying to call close/cancel from within the TagHover Ctrl scope, but trying to call close from a Parent scope.
const TagHover = angular.module('tickertags-shared')
.controller('TagHoverController', TagHoverController)
.factory('TagHover', factory);
TagHoverController.$inject = [
'TagHover'];
function TagHoverController(
TagHover) {
this.$onInit = () => {
console.log('TagHover onInit')
};
this.cancel = () => this.$close();
}
factory.$inject = ['$uibModal'];
function factory($uibModal) {
const display = () => {
const modal = $uibModal.open({
controllerAs: 'tghov',
bindToController:true,
templateUrl: 'tags/tag_hover.html',
windowClass: 'dash-modal',
resolve: {},
controller: 'TagHoverController'
});
};
const off = () => {
$uibModal.close({});
};
return {
display,
off
}
}
module.exports = TagHover;
Here are the docs https://angular-ui.github.io/bootstrap/#/modal
The open method returns a modal instance, an object with the following properties:
close(result) (Type: function) - Can be used to close a modal, passing a result.
I also logged out the $uibModal object and I only see an open function, no close :(
In your case, Your are using Factory for dynamic Modal. so you can use $uibModalStack in the below two ways.
$uibModalStack.dismissAll(); // dismiss all opened modal
$uibModalStack.dismiss(openedModal.key); // dismiss modal by key
Example of dismiss Method.
var top = $uibModalStack.getTop();
if (top) {
$uibModalStack.dismiss(top.key);
}
It's very important to do dismissing the modal during router changes since its dynamic modal.
In general, $uibModal will help to open the modal then each modal is $uibModalInstance, if you want to close modal inside the modal.
Opening Modal on Event
angular.module('myPage')
.controller('PageController', ['$uibModal',
function($uibModal) {
function onModalLink() {
$uibModal.open({
templateUrl: 'app/modals/paymentTpl.html',
controller: 'PaymentModalController as vm',
windowClass: 'generalModal myModal'
});
}
}
]);
To Close from Instance.
angular.module('paymentModal')
.controller('PaymentModalController', [
'$uibModalInstance',
function ChangeRepaymentController($uibModalInstance) {
function onCancel() {
$uibModalInstance.close(repaymentPercentage);
}
}
]);
modalInstance - The modal instance. This is the same $uibModalInstance injectable found when using controller.
WIKI Reference: https://github.com/angular-ui/bootstrap/tree/master/src/modal/docs
This is wrong approach - you can not "just close modal", cause you dont tell which modal to close. I recommend you to redesign this...
You can have a look at $uibModalStack - it stores opened modals and have methods like dismisAll
I use close() method with $uibModal and open() method for manage in AngularJS $uiModal
Open method
vm.lanzarPopShowTask = lanzarPopShowTask;
function lanzarPopShowTask(index){
vm.modalInstance = $uibModal.open({
animation: true,
ariaLabelledBy: 'modal-title-top',
ariaDescribedBy: 'modal-body-top',
templateUrl: '/btask/index/task.html',
size: 'm',
controller: function ($scope) {
vm.task = vm.tasks[index];
vm.index = index;
},
scope: $scope
});
}
And Close method
vm.modalInstance.close();
When doing this I set the modal as a scope variable then use $scope.sweetModal.close() or $scope.sweetModal.dismiss() you just have to remember that if you were to do the following it wouldn't work:
$scope.openModal = function () {
$scope.sweetModal = $uibModal.open({
templateUrl: '/modals/sweetModal.html',
size: 'md',
scope: $scope,
backdrop: true
})
.result.then($scope.modalCloseFunction, $scope.modalDismissFunction);
};
Where as the following would work because of how the variable is set:
$scope.openModal = function () {
$scope.sweetModal = $uibModal.open({
templateUrl: '/modals/sweetModal.html',
size: 'md',
scope: $scope,
backdrop: true
});
$scope.sweetModal.result.then($scope.modalCloseFunction, $scope.modalDismissFunction);
};
I want to create a modal (dialog). I have followed examples on official bootstrap documentation but I stuck. When I am trying to create modal I receive an error
angular.min.js:122 Possibly unhandled rejection: {}
mainController:
angular
.module('app')
.controller('tlmController', function($scope, $http, $timeout, $uibModal, DTOptionsBuilder, DataLoader, TestLines) {
$scope.openTestLineDetails = function(id) {
var modalInstance = $uibModal.open({
size: 'lg',
controller: 'testlineDetailsController',
templateUrl: 'app/client/layout/testlinedetails.tpl.html',
resolve: {
testLineId: function() {
return id;
}
}
});
};
})
and TestlineDetailsController:
angular
.module('app')
.controller('testlineDetailsController', function($scope, $modalInstance, testLineId) {
});
What is wrong with this code? I am using $uibModal ($modal service does not exist) in main controller. When I replace $modalInstance by $uibModalInstance I receive an error too (service $uibModalInstance does not exist), so I have to use $uibModal with $modalInstance. Strage but true.
you can write below code in app.config
app.config(['$qProvider', function ($qProvider) {
$qProvider.errorOnUnhandledRejections(false);
}]);
First of all, check your modal controller script is appended to the main HTML file and if its appended(appears) in the browser (In Chrome, open web developer tools with F12 keyboard button then open the "Elements" tab button) (This is in case you are using some scaffolding tool like generator-angular from Yeoman's team, remember to clear cache in order to get the latest update from your code), because I had the same problem :( and I was reviewing constantly what was wrong with my code then I found out that the browser was not appending the latest script I made (Modal controller), so my code was like yours, but taking your code example:
<!-- In your index.html file, check for this script being appended in your browser -->
<script src="testlineDetailsController.js"></script>
//In your parent controller
angular
.module('app')
.controller('tlmController', function($scope, $http, $timeout, $uibModal, DTOptionsBuilder, DataLoader, TestLines) {
$scope.openTestLineDetails = function(id) {
var modalInstance = $uibModal.open({
size: 'lg',
controller: 'testlineDetailsController',
templateUrl: 'app/client/layout/testlinedetails.tpl.html',
resolve: {
testLineId: function() {
return id;
}
}
});
};
})
Secondly, make sure you are implementing at least one method from the modal instance service in the modal controller: EDIT: (This is optional, you can hide the modal using the backdrop property from the modal option object)
//In your modal controller
angular.module('app').
controller('testlineDetailsController', function ($scope, $uibModalInstance, testLineId) {
//In case you have the ok and cancel buttons in your modal template
$scope.id = testLineId;
$scope.ok = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
After this, your app should be working.
Now, there is another alternative to get this issue solved, you can directly write the controller function in the property of the modal options object:
//In your parent controller
angular
.module('app')
.controller('tlmController', function($scope, $http, $timeout, $uibModal, DTOptionsBuilder, DataLoader, TestLines) {
$scope.openTestLineDetails = function(id) {
var modalInstance = $uibModal.open({
size: 'lg',
//write an anonymous function instead of naming the controller name.
controller: function ($scope, $uibModalInstance, testLineId) {
$scope.id = testLineId;
$scope.ok = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
},
templateUrl: 'app/client/layout/testlinedetails.tpl.html',
resolve: {
testLineId: function() {
return id;
}
}
});
};
})
This alternative should work also in your app. So I hope this explanation helps you to solve the issue you have.
I am trying to pass an object to a component that is inside an angular material dialog.
The function I use to display the Dialog is:
ctrl.openCampaignSplitDialog = function(ev, split){
$mdDialog.show({
template: '<campaign-split-dialog split="$ctrl.split"></campaign-split-dialog>',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
}).then(function(split) {
ctrl.addCampaignSplit(split);
}, function() {
$scope.status = 'You cancelled the dialog.';
});
};
This correctly opens up the dialog.
This is the code for the component:
angular
.module('app')
.component('campaignSplitDialog', {
templateUrl: 'app/components/campaignSplitDialog/campaignSplitDialog.html',
controller: campaignSplitDialogCntrlr,
bindings:{
split: '<'
}
});
/** #ngInject */
function campaignSplitDialogCntrlr($mdDialog) {
var ctrl = this;
console.log('splitter', ctrl.split);
}
The issue arrises from the fact I am not sure how to pass in the split object from the open dialog function to the component module. In the 'template' URL there I have split="$ctrl.split". I have tried multiple different ways but none worked. I have tried double brackets, plain variable name, and using the controllerAs syntax.
I have also tried passing the value in through the dialog by using the locals:{} paramter but because I do not specify a controller, since it is configured when the component is called upon, it does not appear in the component.
I'll answer the first line of your question - "I am trying to pass an object to a component that is inside an angular material dialog" - as the way you are trying to achieve it doesn't look correct.
CodePen
Markup
<div ng-controller="MyController as vm" ng-cloak="" ng-app="app">
<md-button class="md-primary md-raised" ng-click="vm.open($event)">
Custom Dialog
</md-button>
<script type="text/ng-template" id="test.html">
<md-dialog aria-label="Test">
<campaign-split split="text"></campaign-split>
</md-dialog>
</script>
</div>
JS
angular.module('app',['ngMaterial'])
.component('campaignSplit', {
template: '<div>{{$ctrl.split}}</div>',
bindings:{
split: '<'
}
})
.controller('MyController', function($scope, $mdDialog) {
this.open = function(ev) {
$scope.text = "Hello";
$mdDialog.show(
{
templateUrl: "test.html",
clickOutsideToClose: true,
scope: $scope,
preserveScope: true,
controller: function($scope) {
},
});
};
this.save = function () {
$mdDialog.cancel();
}
})
Hopefully this will point you in the right direction.
Check the property options.locals https://material.angularjs.org/HEAD/#mddialog-show-optionsorpreset
$mdDialog.show({
template: '<campaign-split-dialog split="$ctrl.split"></campaign-split-dialog>',
locals:{
split: $ctrl.split
},
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose:true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
})
The way you currently are doing it, is skipping the dialogs controller.
In this scenario there are three controllers.
1) state controller
2 dialog controller
3) component controller
The proper way to do this is:
ctrl.openCampaignSplitDialog = function(ev, split){
$mdDialog.show({
template: '<campaign-split-dialog split="split"></campaign-split-dialog>',
parent: angular.element(document.body),
targetEvent: ev,
locals: {split: $ctrl.split}
controller: function($scope, split){
$scope.split = split;
},
clickOutsideToClose:true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
}).then(function(split) {
ctrl.addCampaignSplit(split);
}, function() {
$scope.status = 'You cancelled the dialog.';
});
};
This is the code for the component:
angular
.module('app')
.component('campaignSplitDialog', {
templateUrl: 'app/components/campaignSplitDialog/campaignSplitDialog.html',
controller: campaignSplitDialogCntrlr,
bindings:{
split: '<'
}
});
/** #ngInject */
function campaignSplitDialogCntrlr($mdDialog) {
var ctrl = this;
console.log('splitter', ctrl.split);
}
So what is happening is, the variable $ctrl.split is going from the state controller to the dialog controller using locals, then in the dialog controller, you bind it to $scope, then from there you can pass the variable $scope.split to the component tag, that passes the variable to the component bindings
I pass a value to my mdDialog controller to edit the content in a modal, but of the user cancels the modal no adjustments can be saved, but still if I change to content within the modal, I see the changes happening on the list behind (on the parent view) and when I cancel the modal, the changes aren't undone.
The option bindToController is set to true, so a copy should be passed instead of a reference.
vm.editFaq = function (faqToEdit, ev){
var useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && vm.customFullscreen;
$mdDialog.show({
controller: 'editFaqController'
, controllerAs: 'dvm'
, templateUrl: './app/components/faq/modals/editFaq.html'
, parent: angular.element(document.body)
, targetEvent: ev
, clickOutsideToClose: true
, fullscreen: useFullScreen
, locals: { faq : faqToEdit }
, bindToController: true
}).then(function(result){
if(result){
_.findWhere(vm.allFaqs, { _id: faqToEdit._id }) = result;
}
});
$scope.$watch(function () {
return $mdMedia('xs') || $mdMedia('sm');
}, function (wantsFullScreen) {
$scope.customFullscreen = (wantsFullScreen === true);
});
};
So when to modal is hidden, the "then" promise is called and the adjustments can be committed.
I used angular.copy, a friend told me that even with bindToController, or what ever other option of mdDialog that said to work always passes a reference of the object.
you can solve like that:
vm.editFaq = function (faqToEdit, ev){
var useFullScreen = ($mdMedia('sm') || $mdMedia('xs')) && vm.customFullscreen;
faqToEdit = angular.copy(faqToEdit);
$mdDialog.show({
controller: 'editFaqController',
controllerAs: 'dvm',
templateUrl: './app/components/faq/modals/editFaq.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: useFullScreen,
locals: {
faq: faqToEdit
},
bindToController: true
}).then(function(result) {
if (result) {
_.findWhere(vm.allFaqs, {
_id: faqToEdit._id
}) = result;
}
});
}
I'm trying to include an angular-ui modal in my web application but am having issues with getting everything set up.
The documentation indicate that you can use $modalInstance to inject the child controller into the parent controller but I don't quite understand how to go about doing so.
Here is the current code (it is straight from the modal demo from the documentation):
angular.module('myApp.controllers', []).
controller('addContent', function ($scope, $http, $modal, $log){
//modaltest
$scope.items = ['item1', 'item2', 'item3'];
$scope.addTerm = function () {
var newTerm = $modal.open({
templateUrl: 'newTermModal.jade',
controller: newTerms,
resolve: {
items: function () {
return $scope.items;
}
}
});
newTerm.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
}).
controller("newTerms",function($scope, $modalInstance, items){
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
When I run the app like it is now and click the button to open the modal (addTerm function) the app crashes with the error "ReferenceError: newTerms is not defined."
As I mentioned above, the angular-ui site indicates you can inject a controller with $modalInstance but I have not been able to figure out how.
a
Any help would be greatly appreciated!
EDIT
After adding the quotation marks on the pathname as suggested by Chandermani, it seems the modal is loading in the current page rather than the specified template.
I've changed the path to the following: templateUrl:
$scope.addTerm = function () {
var newTerm = $modal.open({
templateUrl: './views/partials/newTermModal.jade',
controller: 'newTerms',
resolve: {
items: function () {
return $scope.items;
}
}
});
A screenshot of the issue follows:
Any idea what could be causing this?
Well you can pass the controller as a string value. I took the default demo sample for modal and changed it to pass controller name instead of controller itself.
See my plunker http://plnkr.co/edit/jpJX4WvHw0SSYm3pAAzq?p=preview
So something like this
controller: 'newTerms',
should work.
I got the same problem, the modal loads main HTML file but not template.
My previous configuration was:
opens dialogs but dialog content is main HTML (like on your pic)
$scope.opts = {
backdrop: true,
backdropClick: true,
dialogFade: false,
keyboard: true,
templateUrl : 'app/reports/modalContent.html',
controller : 'ModalInstanceCtrl',
resolve: {}
};
works as expected
$scope.opts = {
backdrop: true,
backdropClick: true,
dialogFade: false,
keyboard: true,
templateUrl : '/app/reports/modalContent.html',
controller : 'ModalInstanceCtrl',
resolve: {}
};
Sounds like if you put wrong templateUrl, it by default uses main page HTML.
Be sure that you have right path for templateUrl
Hope it will help,
Have you tried to declare a dependency of 'ui.bootstrap' module? Like this:
angular.module('myApp.controllers', ['ui.bootstrap'])
Happened to me today, too. The templateUrl in the controller must match the id for the modal in the html file.
You need to define the newTerms controller before your other controller. Or you can change the code and just create a function inside your main controller with the name newTerms and remove the quotation marks for the name of your controller in your modal.
$scope.addTerm = function () {
var newTerm = $modal.open({
templateUrl: './views/partials/newTermModal.jade',
controller: newTerms,
resolve: {
items: function () {
return $scope.items;
}
}
});
var newTerms = function($scope, $modalInstance, items){
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}