AngularJS how to use promise and defer - angularjs

I have this service:
angular.module('taskModule').service('myService', ['$modal', '$q', myService]);
function myService($modal, $q) {
this.displayModal = function(data) {
return $q(function(resolve, reject) {
$modal.open({
templateUrl: 'taskModule/taskModule/modal.tpl.html',
controller: function() {
this.datas = data;
this.buttonAction = function(id) {
console.log(id);
};
},
controllerAs: 'myCtrl'
});
});
};
}
What should I add to this code to see in console
You clicked the button ok
OR
You clicked the button Cancel
When I call this modal with this code:
myService.displayModal({
title: "This is a modal window",
message: "Please click a button.",
buttons: [{
id: 'ok',
label: 'OK'
}, {
id: 'cancel',
label: 'Cancel'
}, ]
}).then(function(buttonId) {
console.log('You clicked the button', buttonId);
});
Maybe I should use $q.defer(); but I'm novice in AngularJS.

The $modal.open function returns a modal instance which already has a promise that resolves/rejects when the modal is closed/dismissed, so you can just return that promise instead of creating a new one.
To return a value with a promise, you can call close/dismiss with that value - updated below.
function myService($modal, $q) {
this.displayModal = function(data) {
var modalInstance = $modal.open({
templateUrl: 'taskModule/taskModule/modal.tpl.html',
controller: function() {
this.datas = data;
this.buttonAction = function(id) {
console.log(id);
modalInstance.close(id);
};
},
controllerAs: 'myCtrl'
});
return modalInstance.result;
};
}

Related

AngularJS: controller undefined while testing directive with controllers using Jasmine

I need to test the controller my directive is using. but could not reference the controller.
directive.js
(function () {
'use strict';
angular
.module('myModule')
.directive('cabinet', function () {
return {
restrict: 'E',
replace: true,
controller: CabinetThumbnails,
controllerAs: 'ctrl',
bindToController: true,
templateUrl: 'app/components/capture/cabinet.directive.html',
scope: {
thumbnail: '='
}
};
});
function CabinetThumbnails($uibModal, cabinetService, SweetAlert,
spinner, $state, $window) {
var vm = this;
vm.showImage = showImage;
vm.deleteThumbnail = deleteThumbnail;
function showImage() {
if (vm.thumbnail.FileCategoryName === 'OpenDocument') {
$window.open(vm.thumbnail.FileUrl);
}
else {
$uibModal.open({
animation: true,
templateUrl: 'app/components/capture/cabinet.pop-up.html',
controller: ModalCtrl,
controllerAs: 'ctrl',
size: 'lg',
resolve: {
thumbnailData: function () {
return vm.thumbnail;
}
}
});
}
}
function deleteThumbnail() {
//show the popup confirmation
SweetAlert.swal({
title: 'Are you sure to delete ?',
text: 'You will not be able to recover the file once deleted !',
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: 'Delete',
closeOnConfirm: true
},
function (isConfirm) {
if (isConfirm) {
spinner.show();
//call the service to delete here
cabinetService.deleteCabinetFile(vm.thumbnail.CabinetFileID)
.then(function (data) {
//validate the response
if (data != null && data.returnVal === -1) {
SweetAlert.swal('You do not have access to delete ' +
'the screen shot',
'Please contact the owner of the screen shot!',
'error');
} else {
//load all the Thumbnails by reloading the page
$state.reload();
}
})
.catch(function (err) {
SweetAlert.swal('Something went wrong !',
'Please try again later !', 'error');
})
.finally(spinner.hide);
}
});
}
}
function ModalCtrl($scope, $uibModalInstance, thumbnailData,
logger, cabinetService) {
var ctrl = this;
ctrl.thumbnailData = thumbnailData;
ctrl.save = save;
ctrl.cancel = cancel;
//call this method to get executed while the directive loads to open the pop-up
getComments();
function getComments() {
cabinetService
.getComments(thumbnailData)
.then(function (data) {
ctrl.comments = data;
})
.catch(function (err) {
logger.error('Unable to get comments, Please try later !',
{ttl: 20000});
});
}
}
}());
MytestSpec.js:
'use strict';
describe('cabinet', function () {
var el,
CabinetThumbnailsController,
scope;
beforeEach(bard.appModule('myModule', bard.fakeLogger));
// Initialize the controller and a mock scope
beforeEach(function () {
bard.inject('$controller', '$compile', '$rootScope', '$q', '$uibModal',
'cabinetService', 'SweetAlert', 'spinner', '$state',
'$window');
scope = $rootScope.$new();
el = angular.element('<div cabinet></div>', {$scope: scope});
$compile(el)(scope);
//CabinetThumbnailsController = el.controller('cabinet');
CabinetThumbnailsController = $controller('CabinetThumbnails', {$scope: scope});
$rootScope.$apply();
});
it('should be initialized', function () {
expect(el).toBeDefined();
});
//controller testing
it('CabinetThumbNails controller to be initialized', function () {
expect(CabinetThumbnailsController).toBeDefined();
});
it('CabinetThumbNails controller showImage method to be called', function () {
expect(CabinetThumbnailsController.showImage).toHaveBeenCalled();
});
});
both the following statements are not working
CabinetThumbnailsController = el.controller('cabinet');
CabinetThumbnailsController = $controller('CabinetThumbnails', {$scope: scope});
and hence calling the controller methods as follows is failing too:
expect(CabinetThumbnailsController.showImage).toHaveBeenCalled();
Separated my controller to a different file and tested the Controller independently. Couldn't get an approach to test the controller along with the directive.

Reload callback not working

The list is not updating when I trigger reload callback function after modal close.
// Inside my view
<div tasty-table
bind-resource-callback="showStudents.loadAllStudentsRecords"
bind-init="showStudents.init"
bind-reload="reloadCallback"
// Inside my controller
...
Other implementations here
...
vm.reloadCallback = function () { alert("Called"); };
vm.delete = function (studId) {
// Show modal
var modalInstance = $uibModal.open({
templateUrl: 'AppScripts/Views/Student/DeleteStudent.html',
controller: 'DeleteStudentCtrl as deleteStudent',
backdrop : 'static',
keyboard : false,
resolve: {
studentId: function () {
return studId;
}
}
});
modalInstance.result.then(function (status) {
if (status === 'ok')
{
vm.reloadCallback();
}
});
The alert was executed when i call the reloadCallback function but the list is not updated
By the way im using "controller as" syntax.
Because of incomplete code i'm not able to understand which method you are using to close the modal window. Check working Plunkr here. Hope it will solve your problem. https://plnkr.co/edit/LnV021AjBXhamG8ygLp1?p=preview
var app = angular.module('plunker', ['ngAnimate','ui.bootstrap']);
app.controller('MainCtrl', function($scope, $uibModal) {
$scope.name = 'World';
$scope.studentId = "123"
$scope.reloadCallback = function(){
alert("Call back")
}
$scope.showModal = function(){
var modalInstance = $uibModal.open({
templateUrl: 'deletestudent.html',
controller: 'DeleteStudentCtrl as deleteStudent',
backdrop : 'static',
keyboard : false,
resolve: {
studentId: function () {
return $scope.studentId;
}
}
});
modalInstance.result.then(function (status) {
if (status === 'ok'){
$scope.reloadCallback();
}
});
}
});
app.controller('DeleteStudentCtrl', function($scope, $uibModalInstance, studentId) {
console.log(studentId);
$scope.closeMe = function(){
$uibModalInstance.close('ok');
}
})
Documentation for modal https://github.com/angular-ui/bootstrap/tree/master/src/modal/docs

How can I call to scope when submit modal?

I'm using angular-ui-bootstrap in my project and working with bootstrap modal. But I'm having a problem with my modal when I submit I can't call to scope and I got a error "$scope.testAlert is not a function"
controller:
$scope.open = function () {
$uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'userModal.html',
controller: function ($scope, $uibModalInstance, user) {
$scope.user = user;
$scope.save = function () {
var editUser = userService.updateUser($scope.user);
editUser.then(function () {
getAllUsers();
$scope.testAlert();
})
$uibModalInstance.close();
}
},
resolve: {
user: function () {
return $scope.user;
}
}
});
}
$scope.testAlert = function () {
alert("Blah blah");
}
$scope.testAlert is on the $scope of the main controller rather than the modal controller. You need to move it like this:
$scope.open = function() {
$uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'userModal.html',
controller: function($scope, $uibModalInstance, user) {
$scope.user = user;
$scope.save = function() {
var editUser = userService.updateUser($scope.user);
editUser.then(function() {
getAllUsers();
$scope.testAlert();
})
$uibModalInstance.close();
$scope.testAlert = function() {
alert("Blah blah");
}
}
},
resolve: {
user: function() {
return $scope.user;
}
}
});
}

use a bootstrap modal without making a seperate controller

I am using a bootstrap modal
Controller.js -
$scope.open = function() {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'views/template.html',
controller: 'controller2',
resolve: {
items: function() {
return $scope.values;
}
}
});
modalInstance.result.then(function(values) {
$scope.new_value = values;
}, function() {
});
};
I don't want to create a new controller since the modal should show values which are constantly changing in the current controller. What should I pass in place of controller2 if I modal to be in the same controller?
You could use the scope option instead of the controller:
$scope.open = function() {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'views/template.html',
scope: $scope,
resolve: {
items: function() {
return $scope.values;
}
}
});
modalInstance.result.then(function(values) {
$scope.new_value = values;
}, function() {
});
};

angular ui bootstrap - How to access modal scope without creating controller

The docs for the $modal service say
The scope associated with modal's content is augmented with 2 methods:
-$close(result)
-$dismiss(reason)
Those methods make it easy to close a modal window without a need to create a dedicated controller.
I'm wondering how to access this scope without creating a dedicated controller.
Try this:
$scope.openModal=function(){
$scope.modalInstance=$modal.open({
templateUrl: 'xyz.html',
scope:$scope
});
}
$scope.close=function(){
$scope.modalInstance.dismiss();
};
now you can use ng-click="close()" in your temnplate file.
ı used this code.
module.service('ModalService', function ($modal) {
var modalOptions = {
backdrop: true,
keyboard: true,
modalFade: true,
templateUrl: null
};
this.show = function (customModalDefaults) {
var tempModalOptions = {};
angular.extend(tempModalOptions, modalOptions, customModalDefaults);
if (!tempModalOptions.controller) {
tempModalOptions.controller = function ($scope, $modalInstance) {
$scope.modalOptions.ok = function (result) {
$modalInstance.close(result);
};
$scope.modalOptions.close = function (result) {
$modalInstance.dismiss('cancel');
};
};
}
return $modal.open(tempModalOptions).result;
};
});
call:
var modalOptions = {
backdrop: true,
modal: true,
size: scope.options.size || 'lg',
templateUrl: '/Apps/inekle/views/common/include_modal.html?v=1',
controller: [
"$scope", "$modalInstance", function ($scope, $modalInstance) {
$scope.model = {
template: scope.options.template,
title: scope.options.title
};
$scope.close = function () {
$modalInstance.dismiss('close');
};
}
]
};
ModalService.show(this.options).then(function (model) {},function (error) { });

Resources