Using Angular - UI Bootstrap
I am passing data into a modalInstance like the below. In the modal, users have the ability to create new items. On the save button press, a new item is sent to the server. I need the ability to refresh the modal instance with the updated data from $scope.items. Note, the modal doesn't close on the save, so I can't just re-open it. Any help would be greatly appreciated.
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function () {
// post updated $scope.items to server
// get fresh $scope.items from server
// notify modal of the updated items
}, function () {
});
};
});
You can try just to create scope for your $modalInstance as a child of current $scope like this:
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
scope: $scope
});
So now after add some item to your items everything will work fine.
For more info you can take a look at description of $modal directive on the angular bootstrap page:
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 provided scope). Defaults to $rootScope
Demo: http://plnkr.co/edit/khzNQ0?p=preview
Hope, it will resolve your problem ;)
Related
I am using ui-router for routing in my angularjs app and ui-bootstrap for UI.In my app on entering a state i am opening a uibmodal which basically returns a uibmodalinstance but when i change a state using
$state.go('dashboard')
Inside my controller it is changing the state but didn't closing modal.
So i want modal to be closed on exiting the state.
i Have written following code but some part of code doesn't work.
please see coding and the comments for not working part
$stateProvider.state('makeabid',{
parent: 'dashboard',
url: '/makeabid/{id}',
data: {
authorities: ['ROLE_USER'],
pageTitle: 'global.menu.makeabid'
},
onEnter: ['$stateParams', '$state', '$uibModal', function($stateParams, $state, $uibModal) {
$uibModal.open({
templateUrl: 'app/dashboard/makeabid/makeabid.html',
controller: 'MakeabidController',
controllerAs: 'vm',
backdrop: true,
size: 'lg'
}).result.then(function () {
$state.go('dashboard');
});
}]
//this part doesnt work
,onExit:['$uibModalInstance','$stateParams', '$state',function ($uibModalInstance,$stateParams, $state) {
$uibModalInstance.close();
}]
});
My Controller Coding is as follows : -
MakeabidController.$inject = ['$stateParams','$state','$uibModalInstance','MakeabidService'];
function MakeabidController( $stateParams, $state, $uibModalInstance, MakeabidService) {
var vm = this;
loadAll();
vm.clear = clear;
vm.save = save;
function clear () {
$uibModalInstance.close();
}
function save() {
// console.log(vm.comparableData);
}
function loadAll() {
vm.comparableData = MakeabidService.getobject();
if(angular.isUndefined(vm.comparableData)){
//$uibModalInstance.close(); //It doesn't work
$state.go('dashboard'); //This is working
}
}
}
AnyOne Please Tell me solution for closing the uibmodal on changing state
I solved it by adding $uibModalStack.close() in my app.run
function run($uibModalStack) {
$rootScope.$on('$stateChangeStart', function() {
$uibModalStack.dismissAll();
});
}
You can tap into to some of the $stateProvider events.
I do something similar in one of my apps (in coffeescript, but you get the idea)
#$scope.$on '$stateChangeStart', (e, to, top, from, fromp) =>
#$uibModalInstance.close()
Basically, in your controller that handles the modal, you will watch for the $stateChangeStart event, and when you catch it, you can close the modal.
See https://github.com/angular-ui/ui-router/wiki, specifically the section on State Change Events
---EDIT---
I just noticed that these calls are deprecated. If you are using UI-Router > 1.0, there is some documentation here on how to migrate: https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-change-events
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 have two scopes and need to combine them. Does anyone know the best way to do this? below are the two scopes. the second one comes from a service
The first scope, retrieves info from database using PHP SLIM RESTful API
Data.get('posts').then(function(data){
$scope.posts = data.data;
});
The second scope retrieves info from database via a service
dataShare.getconfigs().then(function(data){
$scope.configs = data;
});
UPDATE:
When I open the modal to edit I only get the $scope.posts. I am not currently passing through the $scope.configs
$scope.open = function (p,size) {
var modalInstance = $uibModal.open({
templateUrl: 'views/postsEdit.html',
controller: 'postsEditCtrl',
size: size,
resolve: {
item: function () {
return p;
}
}
}); ...
The problem is that $modal.open will create new isolated scope which will be used inside of modal controller and template. This new scope is going to be a direct child of the $rootScope, and thus it will not inherit from your $scope. However, what you want is to inherit from the $scope object from which you open a modal. For this configure modal like this:
$scope.open = function(p, size) {
var modalInstance = $uibModal.open({
templateUrl: 'views/postsEdit.html',
controller: 'postsEditCtrl',
size: size,
scope: $scope, // <-- use $scope as a parent to for modal scope
resolve: {
item: function() {
return p;
}
}
});
};
I have an app that uses dynamic routing to load modal windows, with each window displaying one "activity" object from a JSON file. Currently I'm using the route to determine which card is visible, and then calling a data service to fill in the data based on a match with the route name.
But I don't like this solution, as it isolates my current card from the context of the array. I would far prefer to be able to pass the card object from the template, because then I will know what the $index is, which I can then use to navigate to "prev" and "next" elements.
If I have this mark-up:
<div ng-controller="MenuCtrl">
<ul class="menu">
<li ng-repeat="card in cards">
{{ card.shortName }}
</li>
</ul>
</div>
Which triggers this $routeProvider:
$routeProvider
.when('/page/:name', {
templateUrl : 'modalContainer',
controller : 'ModalContainerCtrl'
})
Which brings up this controller:
.controller('ModalContainerCtrl',['$scope', '$modal', '$route', function($scope, $modal, $route) {
var modalInstance = $modal.open({
templateUrl : '../assets/templates/modal.html',
controller: 'ModalCtrl'
});
$scope.activity = $route.current.pathParams.name;
console.log($scope.activity);
//Modal controls
$scope.close = function () {
console.log("close!");
$modalInstance.close();
};
}])
is there any way I can pass the card object to ModalContainerCtrl via this routing or any other means?
You can pass a scope object to a modal window controller using the resolve (definition of resolve Members that will be resolved and passed to the controller as locals; it is equivalent of the resolve property for AngularJS route). So in your case it can be done like this:
.controller('ModalContainerCtrl',['$scope', '$modal', '$route', function($scope, $modal, $route) {
//your card object
$scope.card = '';
var modalInstance = $modal.open({
templateUrl : '../assets/templates/modal.html',
controller: 'ModalCtrl',
resolve: {
card: function () {
return $scope.card;
}
}
});
$scope.activity = $route.current.pathParams.name;
console.log($scope.activity);
//Modal controls
$scope.close = function () {
console.log("close!");
$modalInstance.close();
};
}])
and in the modal controller:
var ModalCtrl = function ($scope, $modalInstance,card) {
//Modal controls
//card now can be used over here
$scope.close = function () {
console.log("close!") //This will now run
modalInstance.close();
};
}