How to call MVC Web API Controller after AngularJS popup completes - angularjs

I have an AngularJS module with code that calls a modal popup. I also have code that calls an MVC Web API controller method. Both of these functions work independently of one another right now. What I would like to happen is after the user clicks the OK button on the modal, I want to get the value of the modal text box and send it to the API controller as a parameter. The code I have so far is below:
app.js:
(function () {
'use strict';
var app = angular.module("CRNApp", ['ui.bootstrap','trNgGrid']);
var MainController = function ($scope, $http, $log, $uibModal) {
$scope.showGrid = false;
$scope.showPolicyScreen = false;
$scope.CRNViewModel = {
policyId: 0
};
$scope.openPolicyId = function () {
$uibModal.open({
templateUrl: 'templates/popupGetPolicy.cshtml',
backdrop: false,
windowClass: 'modal',
controller: function ($scope, $uibModalInstance, $log, CRNViewModel) {
$scope.CRNViewModel = CRNViewModel;
$scope.submit = function () {
}
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
},
resolve: { CRNViewModel: function () { return $scope.CRNViewModel; } }
});//end of modal.open
}; // end of scope.open fu
$scope.policyLookup = function (policyNumber) {
$scope.loading = true;
$scope.CRNViewModel.policyId = policyNumber; //"WCZ25999"
$http.post("/api/Policy"
, $scope.CRNViewModel
, { header: { 'Content-Type': 'application/json' } })
.then(function (response) {
$scope.policy = response.data;
$scope.loading = false;
$scope.showGrid = false;
$scope.showPolicyScreen = true;
})
.catch(function (error) {
console.log(error);
$scope.loading = false;
$scope.showGrid = false;
});
};
};
app.controller("MainController", MainController);
}());
The MVC API Controller method:
// POST: api/Policy
public IHttpActionResult Post([FromBody]CRNViewModel policy)
{
CRNViewModel _crnVM = new CRNViewModel();
IConditionalRenewalNotices _crn = new ConditionalRenewalNoticesRepository();
_crnVM = _crn.GetPolicyByPolicyId(policy.PolicyId);
return Json(_crnVM);
}

Return the textbox value when you close the $uibModalInstance instance and then add a callback for the modal result:
var modal = $uibModal.open({
templateUrl: 'templates/popupGetPolicy.cshtml',
backdrop: false,
windowClass: 'modal',
controller: function($scope, $uibModalInstance, $log, CRNViewModel) {
$scope.CRNViewModel = CRNViewModel;
$scope.submit = function () {
// pass in the value you want to return
$uibModalInstance.close('WCZ25999');
}
$scope.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
},
resolve: { CRNViewModel: function() { return $scope.CRNViewModel; } }
});
modal.result.then(function (value) {
$scope.policyLookup(value);
});

Related

adding several functions to one controller angular

Im trying to add another function to my controller but it keeps breaking the controller.
here is my code:
.controller('ClimbController', [
'$scope', '$stateParams', 'Climbs', function(
$scope, $stateParams, Climbs) {
var climb_id = $stateParams.climbId;
var areaId = $stateParams.areaId;
if (!isNaN(climb_id)) {
climb_id = parseInt(climb_id);
}
if (!isNaN(areaId)) {
areaId = parseInt(areaId);
}
$scope.selected_ = {};
$scope.items = [];
$scope.details = true;
// looping though all data and get particular product
$scope.selectClimb = function(areas){
areas.forEach(function(data) {
if(data._id == climb_id){
$scope.selected_ = data;
}
});
}
// get all posts // try some function to get a single produt from server
$scope.getPosts = function(){
Climbs.getPosts()
.success(function (data) {
// data = feed.json file
var climbs = [];
data.areas.map(function(area) {
if (area._id === areaId) {
climbs = area.climbs;
}
});
$scope.selectClimb(climbs);
})
.error(function (error) {
$scope.items = [];
});
}
$scope.getPosts();
}
])
And I ned to add this to it:
.controller('MyCtrl', function($scope, $ionicModal) {
$ionicModal.fromTemplateUrl('test-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
});
When I try to add this to the code it breaks it. I nee to either add it as another function or whatever is needed to add it to the code.
Thanks so much
Assuming that you want to merge 'MyCtrl functions into ClimbController then
.controller('ClimbController', ['$scope', '$stateParams', 'Climbs','$ionicModal', function($scope, $stateParams, Climbs,$ionicModal) {
var climb_id = $stateParams.climbId;
var areaId = $stateParams.areaId;
if (!isNaN(climb_id)) {
climb_id = parseInt(climb_id);
}
if (!isNaN(areaId)) {
areaId = parseInt(areaId);
}
$scope.selected_ = {};
$scope.items = [];
$scope.details = true;
// looping though all data and get particular product
$scope.selectClimb = function(areas){
areas.forEach(function(data) {
if(data._id == climb_id){
$scope.selected_ = data;
}
});
}
// get all posts // try some function to get a single produt from server
$scope.getPosts = function(){
Climbs.getPosts()
.success(function (data) {
// data = feed.json file
var climbs = [];
data.areas.map(function(area) {
if (area._id === areaId) {
climbs = area.climbs;
}
});
$scope.selectClimb(climbs);
})
.error(function (error) {
$scope.items = [];
});
}
$scope.getPosts();
$ionicModal.fromTemplateUrl('test-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
});
$scope.openModal = function() {
$scope.modal.show();
};
$scope.closeModal = function() {
$scope.modal.hide();
};
//Cleanup the modal when we're done with it!
$scope.$on('$destroy', function() {
$scope.modal.remove();
});
// Execute action on hide modal
$scope.$on('modal.hidden', function() {
// Execute action
});
// Execute action on remove modal
$scope.$on('modal.removed', function() {
// Execute action
});
}])

Need help completing unit test for angular $modal

I am trying to get the "make sure modalInstance.result.then is executed" test in my code to pass. Right now it says Expected [ undefined, 'http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com' ] to contain 'http://www.pressboardmedia.com' I believe this has something to do with the promise needing to be mocked so it passes along the campaignLink but I am unsure if this is the problem and cannot seem to get it to work regardless. please let know if you have any ideas.
Thanks!
Controller File
angular.module('pb.campaignLinks.controllers')
.controller('CampaignLinksController', ['$scope', '$timeout', '$modal', '$stateParams', 'global', 'campaignLinkService', function ($scope, $timeout, $modal, $stateParams, global, campaignLinkService) {
$scope.init = function (currentView) {
$scope.partialViews = {
campaignLinkList: "/app/campaignLinks/views/_list.html",
};
$scope.currentView = currentView;
$scope.getCampaignLinks(currentView, 10);
};
$scope.getCampaignLinks = function (currentView, length, continuationToken) {
// When loading list items, display loading image
if ($scope.campaignLinks) $scope.campaignLinks.loading = true;
var promiseObj = null;
if (currentView.campaignId && currentView.campaignId !== 0 && !currentView.buyRequestId) {
promiseObj = campaignLinkService.getCampaignLinks(global.activeOrganizationId, currentView.campaignId, length, continuationToken)
} else if (currentView.campaignId && currentView.buyRequestId && currentView.campaignId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getCampaignBuyRequestLinks(global.activeOrganizationId, currentView.campaignId, currentView.buyRequestId, length, continuationToken);
} else if (currentView.webSiteId && currentView.buyRequestId && currentView.webSiteId !== 0 && currentView.buyRequestId !== '') {
promiseObj = campaignLinkService.getWebSiteBuyRequestLinks(global.activeOrganizationId, currentView.webSiteId, currentView.buyRequestId, length, continuationToken);
}
if (promiseObj) {
promiseObj.then(function (data) {
// If there are already some campaign links being displayed, add newly loaded list to the end
if ($scope.campaignLinks) {
$scope.campaignLinks.continuationToken = data.continuationToken;
$scope.campaignLinks.total += data.total;
$.each(data.items, function (index) {
$scope.campaignLinks.items.push(data.items[index]);
});
} else {
// Otherwise add loaded list to scope
$scope.campaignLinks = data;
}
// When done loading, hide loading image
$scope.campaignLinks.loading = false;
});
}
};
$scope.openAddCampaignLink = function (campaignId) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function (campaignLink) {
// Add new item to list, otherwise wait for it to be loaded manually.
$scope.campaignLinks.items.unshift(campaignLink);
$scope.campaignLinks.total += 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
$scope.openRemoveCampaignLink = function (campaignId, campaignLink, index) {
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_delete.html',
controller: 'RemoveCampaignLinksModalController',
resolve: {
campaignId: function () {
return campaignId;
},
campaignLink: function () {
return campaignLink;
}
}
};
var modalInstance = $modal.open(modalOptions);
modalInstance.result.then(function () {
// Splice the deleted item from the list without reloading all
$scope.campaignLinks.items.splice(index, 1);
$scope.campaignLinks.total -= 1;
}, function () {
console.log('Modal dismissed at: ' + new Date());
});
};
// Once everything is loaded, initialize controller
// init();
}]);
Test file:
describe('CampaignLinksController', function () {
//make module avalible to tests
beforeEach(module('pb.campaignLinks.controllers'));
beforeEach(module('ui.router'));
beforeEach(module('ui.bootstrap'));
var $controller;
var mockPromiseObj;
var length = 200;
var mockModal = {};
var mockCampaignLinks = {
total: 3,
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
};
var mockCurrentView = {};
var mockGlobal = { activeOrganizationId: 54 };
var continuationToken = {
nextRowKey: 'fdsf2',
nextPartitionKey: '5432gee'
};
var campaignDetails = {
campaignId: 453,
campaignLink: 'http://www.pressboardmedia.com',
index: 1
};
var mockCampaignLinkService = {
//move campaignDetails here
campaignLinks: {
total: 3,
//length here
items: ['http://www.link1.com', 'http://www.link2.com', 'http://www.link3.com']
},
//all but delete must return a promiseObj
getCampaignLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignLinks').and.returnValue(mockPromiseObj),
getCampaignBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getCampaignBuyRequestLinks').and.returnValue(mockPromiseObj),
getWebSiteBuyRequestLinks: jasmine.createSpy('mockCampaignLinkService.getWebSiteBuyRequestLinks').and.returnValue(mockPromiseObj),
deleteCampaignLink: jasmine.createSpy('mockCampaignLinkService.deleteCampaignLinks')
};
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
beforeEach(inject(function ($rootScope) {
controller = $controller('CampaignLinksController',
{
$scope: scope,
$modal: mockModal,
//$stateParams: mockStateParams,
global: mockGlobal,
campaignLinks: mockCampaignLinks,
campaignLinkService: mockCampaignLinkService,
currentVeiw: mockCurrentView,
//promiseObj: mockPromiseObj
});
}));
describe('openAddCampaignLink()', function () {
var actualOptions;
var modalOptions = {
templateUrl: '/app/campaignLinks/views/_add.html',
controller: 'AddCampaignLinksModalController',
resolve: {
campaignId: jasmine.any(Function)
}
};
beforeEach(inject(function ($q) {
mockModal.open = function (options) {
actualOptions = options;
var defer = $q.defer();
defer.resolve();
return { result: defer.promise };
}
}));
it("make sure modalInstance.result.then is executed", function () {
scope.campaignLinks = mockCampaignLinkService.campaignLinks;
scope.openAddCampaignLink(campaignDetails.campaignId, campaignDetails.campaignLink, campaignDetails.index);
scope.$digest();
expect(scope.campaignLinks.total).toEqual(4);
expect(scope.campaignLinks.items).toContain(campaignDetails.campaignLink);
});
});
I think your problem is that the argument "campaignLink" that is supplied to your modalInstance.result.then function will always be undefined when you test this. The code that calls the modal close should be tested that it is supplying the campaignLink correctly. You only want to test that the proper code gets executed when the modal is closed. We do that by supplying a function that can be tested on it's own to the modalInstance.result.then call instead of doing an inline function so it can be tested easier.
Here's an example:
Here's the code that opens the modal:
$scope.editGradeClick = function () {
var modalInstance = $modal.open({
templateUrl: templateSrv.templateUrl('/Templates/App/Courses/CourseLessonGradeModal.html'),
controller: courseLessonGradeModalBootstrap,
backdrop: 'static',
keyboard: false,
resolve: {
data: $scope.editGradeModalResolve
}
});
modalInstance.result.then(
null,
$scope.editGradeModalDismissCallback
);
};
Notice how we supply a function $scope.editGradeModalDismissCallback instead of writting an inline function there for a modal dismiss. This allows us to test that logic in it's own test.
Now here is the test. We only care that the above function was called since we will be testing the specific function in it's own test. That happens at the last line in the test.
var $controllerConstructor, $scope, $q;
beforeEach(function () {
module('appModule');
inject(function ($controller, $rootScope, _$q_) {
$controllerConstructor = $controller;
$scope = $rootScope.$new();
$q = _$q_;
});
});
it('should execute $scope.editGradeModalDismissCallback when modal is dismissed', inject(function (templateSrv) {
var $modal = {};
$modal.open = function () {
var queryPromise = $q.defer();
queryPromise.reject();
return { result: queryPromise.promise };
};
$controllerConstructor('CourseLessonGradeListCtrl', { $scope: $scope, $modal: $modal, templateSrv: templateSrv});
spyOn($modal, "open").andCallThrough();
spyOn($scope, "editGradeModalDismissCallback");
$scope.editGradeClick();
$scope.$root.$digest();
expect($scope.editGradeModalDismissCallback).toHaveBeenCalled();
}));
I hope this helps you. In this example we are rejecting the promise because we are testing the modal dismiss not close, fyi...

$http.get to resource in angularjs

How would i change the following code form $http.get to a $resource
//The created resource (not using it for now)
hq.factory('LogsOfUser', function ($resource) {
return $resource('/HQ/Graph/GetLoggedinTimes?userName=:userName', {
userName: '#userName'
})
});
//The Controller
var ModalViewLogActionsCtrl = function ($scope, $http, $log, LogsOfUser, $modal) {
$scope.openLogs = function (userName) {
$http.get("/HQ/Graph/GetLoggedinTimes?userName=" + userName).success(function (data) {
var modalInstance = $modal.open({
templateUrl: 'LogView.html',
controller: 'ModalLogViewInstance',
resolve: {
items: function () {
//$scope.items = data;
$log.log(data);
$scope.items = data;
return $scope.items; //return data;
},
userName: function () {
return userName;
}
}
});
}).error(function () {
alert("eror :(");
});;
};
};
You've already done most of the work. All you need now is to call the service inside the controller :
LogsOfUser.query({
userName: userName
}, function success(data) {
//your code
}, function err() {
alert("Error")
});
Use query to get an array of data, and get to get a single document.
Here is a example how to call a resource from a controller:
app.controller('MainCtrl', function($scope, $resource) {
var userName = 'Bob';
var LoggedinTimes = $resource('/HQ/Graph/GetLoggedinTimes');
var data = LoggedinTimes.get({userName : userName}, function () {
console.log(data);
});
});
First, you would want to move data-related logic behind a Service, so your controller doesn't know about server-specifics. More importantly, your Service becomes reusable as all services in AngularJS are global singletons. your controller stays small, as it should be.
Next, your controller would call getLoggedIntimes() and work with the outcome as if the data is there. The result of a $resource.get() or similar functions return an empty object or array which fills itself when the REST call returns with data.
In your service you would do the actual $resource.get().
something along the lines of the following pseudo code:
//The Controller
var ModalViewLogActionsCtrl = function ($scope, MyService, $log, LogsOfUser, $modal) {
$scope.openLogs = function (userName) {
var items = MyService.getLoggedInTimes(userName);
var modalInstance = $modal.open({
templateUrl: 'LogView.html',
controller: 'ModalLogViewInstance',
resolve: {
items: function () {
$scope.items = items;
return $scope.items;
},
userName: function () {
return userName;
}
}
});
};
};
app.service('MyService', function ($resource) {
var loggedInResource = $resource('/HQ/Graph/GetLoggedinTimes/:userName');
return {
getLoggedInTimes: functio(username) {
return loggedInResource.get({
username: username
});
}
};
});

How to pass data to an angular-foundation modal $scope?

I am using angular-foundation and specifically the modal http://madmimi.github.io/angular-foundation/#/modal , i am confused in how to pass data to a modal while using one controller , i want to take an array value and update the modal to show a particular user info ,Ex: $scope.updateUserInfo = $scope.user[index] , the only issue is how to pass the data to the modal .
myApp.controller('users',function ($scope,$location,$http,$modal,msg) {
$http.get('api/v1/users')
.success(function (data,status) {
$scope.user = data;
})
.error(function (data,status) {
$location.path('/login');
});
$scope.showWrite = function () {
$scope.write = true;
}
$scope.closeWrite = function () {
$scope.write = false;
$scope.newUser = '';
}
$scope.save = function () {
$http.post('api/v1/users/store',$scope.newUser)
.success(function (data,status) {
$scope.user.unshift({
id: data,
first_name: $scope.newUser.first_name,
last_name: $scope.newUser.last_name,
email: $scope.newUser.email,
role: $scope.newUser.role
});
$scope.write = false;
$scope.newUser = '';
})
.error(function (data,status) {
alert('failed');
});
}
$scope.confirmDelete = function (index,id) {
msg.confirmDelete().then(function(value) {
$scope.text = msg.getText();
$http.get('api/v1/users/destroy/'+id)
.success(function (data,status) {
$scope.user.splice(index,1);
})
.error(function (data,status) {
alert('Error : Operation failed');
});
});
}
$scope.showUserInfo = function () {
}
$scope.userUpdate = function () {
}
$scope.showUserUpdate = function (index) {
$modal.open({
templateUrl: 'partials/message/update.html',
controller: 'users'
});
}
});
To Pass the data to $modal you need to update your $modal function something like this:
$scope.showUserUpdate = function (popUpData) {
var modalInstance = $modal.open({
templateUrl: 'partials/message/update.html',
controller: ['$scope', '$rootScope', '$modalInstance',
function($scope, $rootScope, $modalInstance) {
$scope = angular.extend($scope, popUpData);
}],
resolve: {}
});
return modalInstance;
};
So popupData is the data which you want to pass to your modal. popupdata then will be merged with existing scope of that controller. Now you can access popupData keys in your HTML. Remember we are returning modal instance in this function so you can manually close the popup using this intance.
Other way is to use the resolve attribute and inject it to controller:
$scope.showUserUpdate = function (popUpData) {
var modalInstance = $modal.open({
templateUrl: 'partials/message/update.html',
controller: ['$modalInstance', 'data', function($modalInstance, data) {
data.popUpData = ...
}],
resolve: {
data: popUpData
}
});
return modalInstance;
};

AngularJS (Restangular CRUD , Simplify / DRY Controllers?)

Below a small example of what I want to simplify. I have the same structure set up for a few other models, and was wondering if I could prevent typing out the same functionality but with just different messages/model.
Is it possible to reuse a controller & pass parameters? (In this case, the name of the model + the messages that need to be shown...). Ideally, I just want the basic CRUD controller to be reused, but allow custom methods, just in case.
angular.module('employees.controllers', ["templates.app", "ui.bootstrap"])
.controller("EmployeeListController", ["$scope", "$modal", "Restangular", function ($scope, $modal, Restangular) {
var Employee = Restangular.all("employees");
Employee.getList().then(function (employees) {
$scope.employees = employees;
})
$scope.createEmployee = function () {
$modal.open({
templateUrl: 'employees/partials/employees.manage.modal.tpl.html',
controller: 'EmployeeCreateController'
}).result.then(function (employee) {
Employee.post(employee).then(function (newEmployee) {
$scope.messageService.addMessage("success", "Employee was successfully created!");
$scope.employees.push(newEmployee);
});
});
};
$scope.deleteEmployee = function (employee) {
employee.remove().then(function () {
$scope.messageService.addMessage("success", "Employee was successfully deleted!");
$scope.employees = _.without($scope.employees, employee);
});
};
$scope.editEmployee = function (originalEmployee) {
$modal.open({
templateUrl: 'employees/partials/employees.manage.modal.tpl.html',
controller: 'EmployeeUpdateController',
resolve: {
employee: function () {
return Restangular.copy(originalEmployee);
}
}
}).result.then(function (employee) {
employee.put().then(function (updated_employee) {
$scope.messageService.addMessage("success", "Employee was successfully updated!");
var originalIndex = _.indexOf($scope.employees, originalEmployee);
$scope.employees[originalIndex] = updated_employee;
});
});
};
}]).controller("EmployeeCreateController", ["$scope", "$modalInstance", "$timeout", function ($scope, $modalInstance, $timeout) {
$scope.createMode = true;
$scope.form = {};
$scope.employee = {};
$scope.datepicker = {};
$scope.ok = function () {
if ($scope.form.createResource.$valid) {
$modalInstance.close($scope.employee);
}
};
$scope.open = function () {
$timeout(function () {
$scope.datepicker.opened = true;
});
};
$scope.cancel = function () {
$modalInstance.dismiss("cancel");
};
}]).controller("EmployeeUpdateController", ["$scope", "$modalInstance", "employee", function ($scope, $modalInstance, employee) {
$scope.createMode = false;
$scope.form = {};
$scope.employee = employee;
$scope.ok = function () {
if ($scope.form.createResource.$valid) {
$modalInstance.close($scope.employee);
}
};
$scope.cancel = function () {
$modalInstance.dismiss("cancel");
};
}]);

Resources