Angular UI Bootstrap modal display during $http request - javascript

I am trying to create a directive that uses angular ui bootstrap modal. I would like to open this directive from my controller when a $http request is made, and close it when the request resolves. I'm new to angular and a bit stuck. Here's what I've got so far.
expedition.html controller:
.controller('ExpeditionCtrl', ['$http', 'UserFactory', '$scope',
function ($http, UserFactory, $scope) {
var vm = this;
vm.totalItems;
vm.itemsPerPage = 100;
vm.currentPage = 1;
vm.pageChanged = pageChanged;
vm.content = [];
vm.loadingInstance;
vm.open;
fetchPage();
function pageChanged() {
fetchPage();
}
function fetchPage() {
$http.get('myapi?page=' + vm.currentPage + "&limit=" + vm.itemsPerPage)
.then(function(response) {
angular.extend(vm.content, response.data.content);
vm.content = response.data.content;
vm.totalItems = response.data.totalElements;
})
}
}
expedition.html:
<div class="section">
<div class="sectioncontent">
// some html
<uib-pagination total-items="vm.totalItems" ng-model="vm.currentPage" ng-change="vm.pageChanged()" items-per-page="vm.itemsPerPage"></uib-pagination>
</div>
<loading-modal loadingInstance="vm.loadingInstance" open="vm.open"></loading-modal>
</div>
</div>
loadingModal.directive.js:
.directive('loadingModal', ['$uibModal',
function($modal) {
return {
transclude: true,
restrict: 'EA',
template: '<div ng-init="open()"> Test Loading </div>',
scope: {
loadingInstance: "=",
open: "="
},
link: function(scope, element, attrs) {
scope.open = function(){
scope.loadingInstance = $modal.open({
templateUrl: 'app/templates/loadingModal.tpl.html',
controller: scope.useCtrl,
size: 'sm',
windowClass: 'app-modal-window',
backdrop: true,
});
scope.loadingInstance.result.then(function(){
scope.initialized = true;
console.log('Finished');
}, function(){
scope.initialized = true;
console.log('Modal dismissed at : ' + new Date());
});
};
}
};
}]);
loadingModal.tpl.html:
<div class="modal-body">
Loading ....
</div>

Ok, so I was able to do this by using a factory. Then in the controller, I call LoadingModalFactory.open() when I initiate a $http request, and LoadingModalFactory.modalInstance.close() when the request resolves. Maybe there's a better way to do this, but for now this is working.
.factory('LoadingModalFactory', ['$uibModal', function($uibModal) {
var modalInstance;
var loadingModalFactory = {
open: open,
modalInstance: modalInstance,
};
return loadingModalFactory;
function open() {
loadingModalFactory.modalInstance = $uibModal.open({
templateUrl: 'app/components/modals/templates/loadingModal.tpl.html',
size: 'sm',
windowClass: 'app-modal-window',
backdrop: true,
});
}
}]);

In your fetchPage() function:
Open the modal and return its object to a variable
Run the $http call and in the resolution, close the modal with its stored variable reference
var modal = $uibModal.open({
//your modal config
});
$http.get(...).then(function(response) {
modal.close();
});
I may be going outside of the question, but you don't have to do this in a directive. You can still modularize this by using a template for the modal and a controller for the modal defined elsewhere.
If you need to do this in a directive, you could pass the http get function into the directive with the '&' scope property.

Related

How to access the modalInstance $scope from outside the model

I want to update some value of a $modal in AngularJS but unable to understand how I can do this. Sample code is below:
var modalInstance;
function setupCall(data) {
var templateURL = 'partials/Chat.html';
var cssClass = 'medium-Modal';
modalInstance = $modal.open({
backdrop: "static",
keyboard: false,
backdropClick: false,
windowClass: cssClass,
templateUrl: templateURL,
controller: function ($scope, $modalInstance) {
$scope.updateStatus=function() {
...
}
}
});
modalInstance.result.then(function() {
});
}
// first time i call this function to open model
setupCall(event);
Now when model open successfully and if I received some update from service and I again want to show updated values in a model then how I can call updateStatus() from outside the model. I try to using
modalInstance.updateStatus(..) but it is not working. Can someone tell me a proper way to do this?
You can pass a scope option to $modal, and then use AngularJS events
var modalScope = $rootScope.$new();
myService.doSomethingAsync(function (data) {
$rootScope.$emit('some event', data);
});
$modal.open({
scope: modalScope,
controller: function ($scope) {
/* ... */
$scope.$on('some event', function() {
$scope.updateStatus();
});
}
});
You can use $broadcast to call that method. For example, after you received update from your service in your view's controller (where you are calling setupCall or launching the modal), do this:
$rootScope.$broadcast("dataUpdatedFoo", {newData: "bar"));
Now, inside your controller of modal, register a listener for this:
$scope.$on("dataUpdatedFoo", function(e, data) {
$scope.updateStatus();
});
Thanks everyone. I resolve this by adding custom eventlistener.
var listeners = [];
function _addEventListener(listener) {
listeners.push(listener);
return listener;
}
function _removeListener(listener) {
for (var i=0; i < listeners.length; i++){
if (listeners[i] === listener){
listeners.splice(i, 1);
break;
}
}
}
function setupCall(data) {
......
modalInstance = $modal.open({
backdrop: "static",
keyboard: false,
backdropClick: false,
windowClass: cssClass,
templateUrl: templateURL,
controller: function ($scope, $modalInstance) {
var listener = _addEventListener(function (event) {
$log.info("chat msg: "+JSON.stringify(event));
});
$scope.$on('destroy', function () {
_removeListener(listener)
});
...

$scope is getting lost while opening a modal on ng-click

When I am trying to open a modal on ng-click the scipe variables is getting lost.
var modalInstance = $modal.open({
templateUrl: 'partials/create.html',
controller: 'AppCreateCtrl',
scope: $scope // <-- I added this
});
You should pass data using the resolve property like this:
var modalInstance = $modal.open({
templateUrl: templateSrv.templateUrl('partials/create.html'),
controller: modalBootstrap,
backdrop: 'static',
keyboard: false,
resolve: {
data: function () {
var result = {};
result.scope = $scope;
return result;
}
}
});
modalInstance.result.then(
function (dataPassedFromModalConroller) {
//this is called when the modal is closed
},
function (dataPassedFromModalConroller) { //Dismiss
//this is called when the modal is dismissed
}
);
Specify the controller for the modal instance like this (we do this in another file):
var modalBootstrap= function ($scope, $modalInstance, data) {
$scope.modalInstance = $modalInstance;
$scope.scope = data.userId;
};
modalBootstrap['$inject'] = ['$scope', '$modalInstance', 'data'];
Your modal template would look something like this:
<div ng-controller="AppCreateCtrl">modal content here</div>

share data between sibling directives

Currently, I am facing one issue related to angularjs directive. I want to send outlet object from directive1 to directive2. Both directives having same controller scope. I tried with emitting event from directive1 to controller, broadcasting that event from controller to directive2 and listening to that event on directive2. but that is not working.
Directive1:
angular.module('moduleName')
.directive('directive1', function() {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
scope.order.entityId = outlet.id;
scope.navigation.currentTab = 'right';
};
}
};
Here, in directive1, scope.selectOutlet() setting outletId to scope.order.entityId. I want to move/set that line to directive2 save function.
Directive2:
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
scope.save = function() {
// Save functionality
// scope.order.entityId = outlet.id; This is what i want to do
};
}
};
});
});
Any help.
you can use a factory or a service. Inject that factory into your directive. Now when you are trying set the data in function written into factory. `app.factory('shared',function(){
var obj ={};
obj.setData = function(){
// call this function from directive 1.
}
return obj;
})`
So if you include this factory into your directives you will get the data in 2 directives.
I will try to make some jsfiddle or plunker. If it is not clear.
Do the following in first directive
angular.module('moduleName')
.directive('directive1', function($rootScope) {
return {
restrict: 'E',
templateUrl: 'directive1.html',
scope: false,
link: function(scope) {
scope.selectOutlet = function(outlet) {
$rootScope.$broadcast('save:outlet',outlet);
//scope.order.entityId = outlet.id;
//scope.navigation.currentTab = 'right';
};
}
};
and in second
angular.module('moduleName')
.directive('directive2', function(config, $rootScope, $state) {
return {
restrict: 'E',
templateUrl: 'directive2.html',
scope: false,
link: function(scope) {
$rootScope.$on('save:outlet',function(event,data){
// do staff here
});
}
};
});

pass simple parameter to angular ui-bootstrap modal?

I see many posts about posting many complicated things to ui-bootstrap modals, but I just want to pass a simple parameter so that I might use it to display different content in the dialog.
For example, I have the main document which has MyDocumentController as mydoc
In MyDocumentController is a function such as
_this.modals = {
inviteUser: function() {
$modal.open({
animation: true,
templateUrl: 'modules/templates/modals/modal-invite-user.html',
controller: 'UserInviteModalController as invite',
size: 'lg'
});
}, ...
And I call it in the main document like so, here is where I want to pass the param from:
<a href="" ng-click="users.modals.inviteUser(returningUser)">
And here is the controller for the modal:
(function() {
'use strict';
angular.module('mymodule')
.controller('UserInviteModalController', function($log, $modalInstance, toastr) {
var _this = this;
_this.someVar = HERE'S WHERE I WANT TO GET THE VALUE returningUser FROM THE NG-CLICK
_this.inviteDialog = {
close: function() {
$modalInstance.close();
},
resendInvite: function() {
toastr.success('A new invite has been sent.');
$modalInstance.close();
}
};
});
})();
What is the process for passing the simple param to the dialog's controller?
Try using resolve:
_this.modals = {
inviteUser: function(returningUser) {
$modal.open({
animation: true,
templateUrl: 'modules/templates/modals/modal-invite-user.html',
controller: 'UserInviteModalController as invite',
size: 'lg',
resolve: {
returningUser: function() {
return returningUser;
}
}
});
}, ...
And then inject it into your controller:
angular.module('mymodule')
.controller('UserInviteModalController', function($log, $modalInstance, toastr, returningUser) {
var _this = this;
_this.someVar = returningUser;

Model binding not working in Angular UI Bootstrap modal

I have simple example using Angular UI Bootstrap modal service. In this example I don't understand why model binding is not working. Instead of seeing "Doing something..." on modal dialog I see "{{message}}". What I need to change?
Example is here:
http://plnkr.co/edit/fJhS3e7At11tJTuNSWAB?p=preview
modal html looks like this:
<div ng-app="myModule">
<div ng-controller="modalInstanceController" class="modal-body">
<div>{{message}}</div>
</div>
</div>
And definition of module and controllers:
var myAppModule = angular.module('myModule', ['ui.bootstrap']);
myAppModule.controller('modalInstanceController', function ($scope, $modalInstance, message) {
var vm = this;
vm.message = message;
});
myAppModule.controller('myController', function ($scope, $modal) {
$scope.open = function open() {
var modalInstance = $modal.open({
templateUrl: 'modal.html',
backdrop: 'static',
//windowClass: 'custom-modal-wait',
dialogFade: false,
keyboard: false,
controller: 'modalInstanceController',
resolve: {
message: function () {
return "Doing something ...";
}
}
});
setTimeout(function(){
modalInstance.close('close');
},5000);
}
});
to use the value you pass to the modal, you need to put it on its scope, so set the modal controller as so:
myAppModule.controller('modalInstanceController', function ($scope, $modalInstance, message) {
$scope.message = message;
});
and remove the ng-controller from modal.html, you are already assigning him a controller when you create the modal instance
ng-controller="modalInstanceController"
your fixed example : http://plnkr.co/edit/vnfL72EBMXsQ1NzlJNEF?p=preview

Categories