Service
angular.module('App').service('producerContactSvc', ['$http', 'configSvc', function($http, configSvc) {
//Reset headers to avoid OPTIONS request (aka preflight)
$http.defaults.headers.common = {};
var _this = this;
_this.getProducerContacts = function(producerId) {
var endpoint = configSvc.backendUrl + '/producerContact/read?producerId=' + producerId;
return $http.get(endpoint)
.then(function(response) {
return response.data;
})
.catch(function(response) {
return response.data;
});
};
_this.addProducerContact = function(producerContact) {
var endpoint = configSvc.backendUrl + '/producerContact/create';
return $http.post(endpoint, producerContact)
.success(function(response) {
return response.data;
})
.catch(function(response) {
return response.data;
});
};
_this.deleteProducerContact = function(producerContactId, producerId) {
var endpoint = configSvc.backendUrl + '/producerContact/delete?producerContactId=' + producerContactId + '&' + 'producerId=' + producerId;
return $http.delete(endpoint)
.then(function(response) {
return response.data;
})
.catch(function(response) {
return response.data;
});
};
_this.updateProducerContact = function(producerContact) {
var endpoint = configSvc.backendUrl + '/producerContact/update';
return $http.put(endpoint, producerContact)
.then(function(response) {
return response.data;
})
.catch(function(response) {
return response.data;
});
};
}]);
Controller
angular.module('App').controller('producerAdminCtrl', ['$scope', '$rootScope', 'producerSvc', '$mdDialog', 'producerContactSvc', 'errorToastSvc', function($scope, $rootScope, producerSvc, $mdDialog, producerContactSvc, errorToastSvc) {
$scope.results = false;
$scope.producerTypeCodes = ['CX', 'FG'];
$scope.producerId = null;
$scope.documents = [];
$scope.selectedDocs = [];
$scope.producerContactRows = [];
$scope.missingName = false;
$scope.producerContactTypeCodes = ['MC', 'BC'];
/**
* Get a list of all producers on load
*/
producerSvc.getAllProducers()
.then(function(response) {
if (response !== null) {
$scope.unusedProducers = response.data;
} else {
$scope.noFound = true;
$scope.results = false;
$scope.message = 'No Data Received';
}
});
/**
* Perform a search on a producer. This will call the backend and find information about the producer searched for
*/
$scope.search = function() {
$scope.documents = [];
$scope.selectedDocs = [];
$scope.query = $scope.selectedItem.producerId;
producerSvc.getProducer($scope.query).then(function(response) {
if (response && response.data) {
$scope.producer = response.data;
$scope.producerId = $scope.query;
$scope.producer.inactiveDate = response.data.inactiveDate === null ? null : new Date(response.data.inactiveDate);
producerSvc.getAllDocs().then(function(response) {
_.forEach(response, function(doc) {
var docObject = {
documentId: doc.documentId,
documentDescription: doc.documentDescription,
documentName: doc.documentName,
selected: false
};
$scope.documents.push(docObject);
});
producerSvc.getProducerDocs($scope.producerId).then(function(response2) {
_.forEach(response2.data, function(docProducer) {
var docId = docProducer.documentId;
_.forEach($scope.documents, function(doc) {
if (docId === doc.documentId) {
doc.selected = true;
$scope.selectedDocs.push(doc);
}
});
});
$scope.documents.sort(function(x, y) {
return (x.selected === y.selected) ? 0 : x.selected ? -1 : 1;
});
$scope.results = true;
$scope.noFound = false;
});
});
} else {
$scope.noFound = true;
$scope.results = false;
$scope.message = 'No Producer Found';
}
});
producerContactSvc.getProducerContacts($scope.query).then(function(response) {
_.forEach(response, function(producerContact) {
var producerContactObject = {
producerContactName: producerContact.producerContactName,
editable: false,
producerContactEmail: producerContact.producerContactEmail,
producerContactType: producerContact.producerContactType,
invalid: false,
producerContactIsNew: false,
producerContactId: producerContact.producerContactId,
producerId: producerContact.producerId
};
$scope.producerContactRows.push(producerContactObject);
});
});
/**
* Add a new producerContact to the producerContactRows array.
*/
$scope.addProducerContact = function() {
var producerId = '';
var producerContactName = '';
var producerContactEmail = '';
var producerContactType = '';
var producerContactObject = {
producerId: producerId,
producerContactName: producerContactName,
editable: true,
producerContactEmail: producerContactEmail,
producerContactType: producerContactType,
invalid: false,
producerContactIsNew: true
};
$scope.producerContactRows.push(producerContactObject);
};
/**
* Enable edit mode on a selected producerContact.
* #param {number} producerContactIndex the index within the producerContactRows array of the producerContact to edit.
*/
$scope.editProducerContact = function(producerContactIndex) {
$scope.producerContactRows[producerContactIndex].editable = true;
};
/**
* Save a selected producerContact.
* #param {number} producerContactIndex the index within the producerContactRows array of the producerContact to save.
*/
$scope.saveProducerContact = function(producerContactIndex) {
if ($scope.producerContactRows[producerContactIndex].producerContactIsNew) {
producerContactSvc.addProducerContact($scope.sanitizeProducerContact($scope.producerContactRows[producerContactIndex])).then(function(response) {
$scope.producerContactRows[producerContactIndex].producerContactId = response.data.producerContactId;
});
$scope.producerContactRows[producerContactIndex].producerContactIsNew = false;
} else {
producerContactSvc.updateProducerContact($scope.sanitizeProducerContact($scope.producerContactRows[producerContactIndex]));
}
$scope.producerContactRows[producerContactIndex].editable = false;
};
/**
* Prompt the user for confirmation they want to delete a producerContact.
* #param {number} producerContactIndex the index within the producerContactRows array of the producerContact to delete.
*/
$scope.deleteProducerContact = function(producerContactIndex, ev) {
var deleteProducerContact = $mdDialog.confirm()
.title('Are you sure you want to delete this ProducerContact?')
.ariaLabel('Delete ProducerContact')
.targetEvent(ev)
.ok('Delete ProducerContact')
.cancel('Cancel');
$mdDialog.show(deleteProducerContact).then(function() {
$scope.performDelete(producerContactIndex);
});
};
/**
* Delete a selected producerContact after verification.
* #param {number} producerContactIndex the index within the producerContactRows array of the producerContact to delete.
*/
$scope.performDelete = function(producerContactIndex) {
console.log($scope.producerContactRows[producerContactIndex]);
if (!$scope.producerContactRows[producerContactIndex].producerContactIsNew) {
producerContactSvc.deleteProducerContact($scope.producerContactRows[producerContactIndex].producerContactId, $scope.producerId);
}
$scope.producerContactRows.splice(producerContactIndex, 1);
};
/**
* Save the producer information to the backend
*/
$scope.saveProducer = function() {
var docObjects = [];
var timestamp = new Date().getTime();
var user = null;
if ($rootScope.apmHeader) {
user = $rootScope.apmHeader.userI;
}
_.forEach($scope.selectedDocs, function(doc) {
var docObject = {
documentid: doc.documentId,
producerId: $scope.producerId,
approvedby: user,
dateapproved: timestamp
};
docObjects.push(docObject);
});
$scope.producer.documentList = docObjects;
producerSvc.saveProducerInfo($scope.producer);
};
}]);
Test Class
describe('Test Producer Contact', function() {
//Add an initialize here:
var $scope;
var $rootScope;
var controller;
// deferred variables
var getProducerDefer;
var getProducerContactsDefer;
var addProducerContactDefer;
var updateProducerContactDefer;
var deleteProducerContactDefer;
var producerContactSvc;
var mockProducerContacts = [{
producerContactId: '11111',
producerId: '1111',
producerContactName: 'abcd',
producerContactEmail: 'abcd#abc.com',
producerContactType: 'cc',
editable: false,
invalid: false,
producerContactIsNew: false
},
{
producerContactId: '11112',
producerId: '1111',
producerContactName: 'efgh',
producerContactEmail: 'efgh#xyc.com',
producerContactType: 'primary',
editable: false,
invalid: false,
producerContactIsNew: false
},
{
producerContactId: '12345',
producerId: '1111',
producerContactName: 'asdh',
producerContactEmail: 'asdh#xyc.com',
producerContactType: 'cc',
editable: false,
invalid: false,
producerContactIsNew: false
}
];
beforeEach(module('FirstSaleApp'));
beforeEach(inject(function($controller, producerSvc, producerContactSvc, _$q_, _$rootScope_) {
$scope = _$rootScope_.$new();
$rootScope = _$rootScope_;
producerContactSvc.deleteProducerContact = function() {
return null;
};
// We use the $q service to create a mock instance of defer
getProducerDefer = _$q_.defer();
getProducerContactsDefer = _$q_.defer();
addProducerContactDefer = _$q_.defer();
updateProducerContactDefer = _$q_.defer();
deleteProducerContactDefer = _$q_.defer();
// Use a Jasmine Spy to return the deferred promise
spyOn(producerSvc, 'getAllProducers').and.returnValue(getProducerDefer.promise);
spyOn(producerContactSvc, 'getProducerContacts').and.returnValue(getProducerContactsDefer.promise);
spyOn(producerContactSvc, 'addProducerContact').and.returnValue(addProducerContactDefer.promise);
spyOn(producerContactSvc, 'updateProducerContact').and.returnValue(updateProducerContactDefer.promise);
spyOn(producerContactSvc, 'deleteProducerContact').and.returnValue(deleteProducerContactDefer.promise);
$controller('producerAdminCtrl', {
$scope: $scope,
producerSvc: producerSvc,
producerContactSvc: producerContactSvc
});
// getProducerDefer.resolve(mockProducers);
getProducerContactsDefer.resolve(mockProducerContacts);
// $scope.$digest();
$rootScope.$digest();
}));
it('controller exists', function() {
expect(controller).not.toBeNull();
});
it('should get the producerContacts from the producerContact service', function() {
// $scope.producerContactRows = $scope.getProducerContacts(1111);
// The length should match
expect($scope.producerContactRows.length).toBe(3); // <-- coming as 0
// The values should be the same too
// Mock 1
expect($scope.producerContactRows[0].producerContactName).toBe(mockProducerContacts[0].producerContactName);
expect($scope.producerContactRows[0].producerContactEmail).toBe(mockProducerContacts[0].producerContactEmail);
expect($scope.producerContactRows[0].producerContactType).toBe(mockProducerContacts[0].producerContactType);
expect($scope.producerContactRows[0].editable).toBeFalsy();
expect($scope.producerContactRows[0].producerContactIsNew).toBeFalsy();
// Mock 2
expect($scope.producerContactRows[1].producerContactName).toBe(mockProducerContacts[1].producerContactName);
expect($scope.producerContactRows[1].producerContactEmail).toBe(mockProducerContacts[1].producerContactEmail);
expect($scope.producerContactRows[1].producerContactType).toBe(mockProducerContacts[1].producerContactType);
expect($scope.producerContactRows[1].editable).toBeFalsy();
expect($scope.producerContactRows[1].producerContactIsNew).toBeFalsy();
// Mock 3
expect($scope.producerContactRows[2].producerContactName).toBe(mockProducerContacts[2].producerContactName);
expect($scope.producerContactRows[2].producerContactEmail).toBe(mockProducerContacts[2].producerContactEmail);
expect($scope.producerContactRows[2].producerContactType).toBe(mockProducerContacts[2].producerContactType);
expect($scope.producerContactRows[2].editable).toBeFalsy();
expect($scope.producerContactRows[2].producerContactIsNew).toBeFalsy();
});
});
I'm new to angularjs - I have started working on an app that uses karma and jasmine to test. I am trying to use deferred promise to stub a method call. However I don't see the data after I digest (or apply) the scope. Any help is appreciated on what I might be missing. Thanks
Related
I need
batchdata:{course_name:"xyz",batch_fees:"1200",---,course_id:"xyz123"}
to sent database but I'm having problem to send course_id along with batchData for that I'm taking course_id from another service that is basically a course table So please look into the code I'm not accessing this -> response.data.data[0]._id because I cant access it outside the function since it local variable so is there any way so that I can bind course_id with batchData object...
app.controller('batch_add', function($scope, $http) {
$http.get("/courses/getall")
.then(function(response) {
if (response.data.length == 0) {
$scope.items = [{ course_name: "No data", course_desc: "No data", course_fees: "No data" }];
} else {
$scope.items = response.data.data;
var course_name_items = []
for (var i = 0; i < $scope.items.length; i++) {
course_name_items.push($scope.items[i].course_name)
}
$scope.course_items = course_name_items;
}
});
$scope.batch_status_items = ['Pending', 'Running', 'Finished', 'Canceled' ]
$scope.batchData={};
$scope.login = {"batchData" : $scope.batchData};
$scope.submitForm = function() {
$scope.login = {"batchData" : $scope.batchData};
$scope.fail = false;
$http({
method : 'POST',
url: 'batches/add',
data : $scope.login
})
.success(function(data) {
if (data.success == true) {
$scope.fail = true;
$scope.success = true;
$scope.success_message = data.message;
var courseName = $scope.batchData.course_name;
$http.get("/courses/search/"+courseName)
.then(function(response) {
if (response.data.length == 0) {
console.log("error");
} else {
$scope.batchData.course_id= response.data.data[0]._id
}
});
toastr.options = {"positionClass": "toast-bottom-right"}
Command: toastr["success"]("A new batch has been added!")
} else {
$scope.fail = true;
$scope.success = false;
$scope.error_message = data.message;
console.log($scope.success_message);
// toastr.error('Something went wrong.', 'Ooops!')
}
});
$scope.batchData.course_id = response.data.data[0]._id
};
});
why don't you get course_id first, then send that id to database along with batchData later?
I've been working at making this script more modularized toady, and I am running into an error. Am I ordering my logic incorrectly?
Error Msg
Uncaught ReferenceError: accountId is not defined
Related Script Line
_.each(_.omit(accounts, _.keys(result.data.accounts)), function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);
});
Script
var debug = 0;
function paramsStr(p) {
var first = true;
var s = '';
_.each(p,function (value,key) {
if (!value) {
return;
}
if (first) {
s += '?';
first = false;
} else {
s += '&';
}
s += key+'='+value;
});
return s;
};
function parseReport(data)
{
var split = data.split('\n');
var results = [];
_.each(split,function (row) {
if (!row || row == "") {
return;
}
var myRow = JSON.parse(row);
myRow.timestamp = moment.utc(myRow.timestamp);
results.push(myRow);
});
return results;
}
function loadReport(report,granularity,startTime,endTime) {
if (debug && _.has(mock.reports,report) && _.has(mock.reports[report],granularity)) {
return jQuery.Deferred().resolve(parseReport(mock.reports[report][granularity])).promise();
}
var params = {
granularity : granularity
};
if (startTime) {
params['start-time'] = startTime.toISOString();
}
if (endTime) {
params['end-time'] = endTime.toISOString();
}
var url = '//analytics.locuslabs.com/api/reports/'+report+paramsStr(params);
return $.ajax({
url : url,
dataType : 'text'
}).then(function (data) {
return parseReport(data);
});
};
$(document).ready(function () {
var placeholder = $(".graph");
var oneMonth = moment().utc().subtract(1, 'months');
var twoWeeks = moment().utc().subtract(2, 'weeks');
//Function call to get the current time
function dateNow(target,timeFormat){
$(placeholder).siblings(target).text(moment(Date.now()).format(timeFormat));
}
function pollData(apiRoot,increment,startDate,label){
loadReport(apiRoot,increment, startDate).then(function (results) {
var totals = [];
var accounts = {};
_.each(results, function (result) {
totals.push([
result.timestamp.valueOf(),
result.data.total
]);
_.each(result.data.accounts, function (account, accountId) {
if (!_.has(accounts, accountId)) {
accounts[accountId] = {
label: account.account.name,
data: []
};
}
accounts[accountId].data.push([
result.timestamp.valueOf(),
account.total
]);
});
_.each(_.omit(accounts, _.keys(result.data.accounts)), function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);
});
});
var data = [{
data: totals,
label: label
}];
_.each(accounts, function (account) {
data.push(account);
});
$(this > ".graph").plot(data, {
grid: {
hoverable: true
},
tooltip: {
show: true
},
xaxis: {
mode: "time"
},
yaxis: {
axisLabel: label
},
legend: {
container: $(this > ".legend")
},
selection: {
mode: "x"
}
});
});
// Reload function within pollData function
document.getElementById(apiRoot + "-reload").addEventListener("click", function() {
pollData(apiRoot,increment,startDate,label);
dateNow(".status","M/D/YYYY H:mm Z");
}, false);
}
//Load Reports
pollData('total-installs', 'day', oneMonth, "Total Installs");
pollData('installs', 'hour', twoWeeks, "Installs (by hour)");
pollData('sessions', 'day', twoWeeks, "Sessions");
pollData('sessions-length', 'day', twoWeeks, "Session Length");
// Selection Feature
// TODO: Add Zoom to selection
// TODO: Overview of Available Data when zoomed.
placeholder.bind("plotselected", function (event, ranges) {
var begin = ranges.xaxis.from.valueOf();
var end = ranges.xaxis.to.valueOf();
$(this).siblings(".selection").text(moment(begin).format("M/D/YYYY H:mm Z") + " to " + moment(end).format("M/D/YYYY H:mm Z"));
/*
var zoom = $("#zoom").prop("checked");
if (zoom) {
$.each(plot.getXAxes(), function(_, axis) {
var opts = axis.options;
opts.min = ranges.xaxis.from;
opts.max = ranges.xaxis.to;
});
plot.setupGrid();
plot.draw();
plot.clearSelection();
}
*/
});
// Update on Initial Poll
// TODO: Ask for location and provide local time.
dateNow(".status","M/D/YYYY H:mm Z");
});
You have no accountId parameter in your function
function (account) {
accounts[accountId].push([result.timestamp.valueOf(), 0]);
I want to return data from a Service function and inject it into a controller via the routeProvider, but only once the data has been fully loaded.
app.js:
.when('/sources', {
templateUrl: 'views/app/source/inventory.html',
controller: 'InventoryCtrl',
pageTitle: 'Data Inventory',
resolve: {
orders: function (OrderService) {
return OrderService.getOrders();
},
sources: function (SourceService) {
return SourceService.getSources();
}
}
})
SourceService:
angular.module('wp.source')
.factory('SourceService', function ($http, $q) {
return {
getSources: function () {
var model = {
sources: []
};
var promises = [];
return $http.get('datasets/project.json')
.then(function (data) {
if(localStorage['files'] != null) {
var files = JSON.parse(localStorage['files']);
for (var i = 0; i < files.length; i++) {
model.sources.push(files[i]);
}
}
var sources = [];
for (var sourceId in data.data.sources) {
var source = data.data.sources[sourceId];
source.id = sourceId;
sources.push(source);
}
angular.forEach(sources, function (source) {
promises.push($http.get('datasets/' + source.filename).then(function (datasource, resolve) {
var metadata = datasource.data.metadata;
var source = {
name: metadata.name,
address: metadata.url,
frequency: metadata.refresh,
type: metadata.type,
tags: metadata.tags,
size: metadata.size,
active: source.active,
sourceID: source.id,
sourceFile: source.filename
};
return source;
}));
});
//var finalPromise = sources.reduce(function (promise, source, index, array) {
// return promise.then(function (a) {
// var query = $http.get('datasets/' + source.filename)
// .then(function (datasource) {
// var metadata = datasource.data.metadata;
// model.sources.push({
// name: metadata.name,
// address: metadata.url,
// frequency: metadata.refresh,
// type: metadata.type,
// tags: metadata.tags,
// size: metadata.size,
// active: source.active,
// sourceID: source.id,
// sourceFile: source.filename
// });
// });
// });
//}, $q.when([]));
//
//finalPromise.finally(function () {
// return model;
//})
$q.all(function () {
return model;
});
});
}
}
});
Controller:
angular.module('wp.source')
.controller('InventoryCtrl', function ($scope, orders, sources) {
$scope.orders = orders.data;
$scope.gridView = true;
$scope.rowView = false;
$scope.allSources = sources.sources;
$scope.shownSources = $scope.allSources;
...
Currently I have the problem that the value is injected before "model" is fully loaded. I tried to pack the subqueries into a $q.all promise, but I don't know exactly where to go from there
Any help would be appreciated
You want to use $q.defer() and returned the deferred promise object.
You code will look something like this.
angular.module('wp.source')
.factory('SourceService', function ($http, $q) {
return {
getSources: function () {
var model = {
sources: []
};
var deffered = $q.defer();
var promises = [];
return $http.get('datasets/project.json')
.then(function (data) {
if(localStorage['files'] != null) {
var files = JSON.parse(localStorage['files']);
for (var i = 0; i < files.length; i++) {
model.sources.push(files[i]);
}
}
var sources = [];
for (var sourceId in data.data.sources) {
var source = data.data.sources[sourceId];
source.id = sourceId;
sources.push(source);
}
angular.forEach(sources, function (source) {
promises.push($http.get('datasets/' + source.filename).then(function (datasource, resolve) {
var metadata = datasource.data.metadata;
var source = {
name: metadata.name,
address: metadata.url,
frequency: metadata.refresh,
type: metadata.type,
tags: metadata.tags,
size: metadata.size,
active: source.active,
sourceID: source.id,
sourceFile: source.filename
};
return source;
}));
});
//var finalPromise = sources.reduce(function (promise, source, index, array) {
// return promise.then(function (a) {
// var query = $http.get('datasets/' + source.filename)
// .then(function (datasource) {
// var metadata = datasource.data.metadata;
// model.sources.push({
// name: metadata.name,
// address: metadata.url,
// frequency: metadata.refresh,
// type: metadata.type,
// tags: metadata.tags,
// size: metadata.size,
// active: source.active,
// sourceID: source.id,
// sourceFile: source.filename
// });
// });
// });
//}, $q.when([]));
//
//finalPromise.finally(function () {
// return model;
//})
$q.all(promises).then(function () {
deferred.resolve(model);
});
});
}
return deferred.promise();
}
});
EDIT As others have mentioned you need to pass your array of promises into $q.all to get this to work right. Also it's worth noting that $q.all will return an array with the results of each promise in the order they were in the promise array.
Here's a plunker demoing the use of defer.
There's more $q.defer and $q.all here in the Angular's Docs.
You will need to use $q.all with array of promises and return it from outer promise:
angular.module('wp.source')
.factory('SourceService', function($http, $q) {
return {
getSources: function() {
var model = {
sources: []
};
return $http.get('datasets/project.json').then(function(data) {
if (localStorage['files'] != null) {
var files = JSON.parse(localStorage['files']);
for (var i = 0; i < files.length; i++) {
model.sources.push(files[i]);
}
}
var sources = [],
promises = [];
for (var sourceId in data.data.sources) {
var source = data.data.sources[sourceId];
source.id = sourceId;
sources.push(source);
}
var promises = sources.map(function(source) {
return $http.get('datasets/' + source.filename).then(function(datasource, resolve) {
var metadata = datasource.data.metadata;
model.sources.push({
name: metadata.name,
address: metadata.url,
frequency: metadata.refresh,
type: metadata.type,
tags: metadata.tags,
size: metadata.size,
active: source.active,
sourceID: source.id,
sourceFile: source.filename
});
});
});
return $q.all(promises).then(function() {
return model;
});
});
}
}
});
You are not using $q.all correctly. The simplest possible fix to your code would be changing
$q.all(function () {
return model;
});
to
$q.all(promises).then(function() {
return model;
});
You're basically not "telling" $q.all which promises it needs to aggregate. Please refer to the documentation for $q and check how all works.
So, I am trying to implement ngGrid data pagination on some data I get from a service. I get the table to display and the search filter works. In my pagingOptions I specify the pageSize as 25, however the table displays all of my data. Another problem I am having is when I click on the pagination buttons, the page turns and goes to the next data, however when I get to page 3/6 or so, my data is deleted and the pagination switches to saying page 3/1. Please help, code below:
var drilldownDirective = function() {
return {
restrict: 'E',
scope: {
tableData: '=',
numPages: '#'
},
controller: function($rootScope, $scope, DashboardFactory) {
var tableData = $scope.tableData;
var dashboardreportid = tableData.dashboardreportid;
var companyid = tableData.companyid;
var companybrandid = tableData.companybrandid;
var startdate = tableData.startdate;
var enddate = tableData.enddate;
var clientdb = tableData.clientdb;
var calltype = tableData.calltype;
var secondarycallval = tableData.secondarycallval;
$scope.gridData = [];
var onSuccess = function(response) {
var d, t, dt, dtobj, obj;
$scope.repdata = [];
$scope.titles = [];
for (d in response.repdata) {
var dtArray = {};
obj = response.repdata[d];
$scope.repdata.push(obj);
for (var d in obj.data) {
var fieldName = d.split(" ").join("_");
var val = obj.data[d];
dtArray[fieldName] = val;
}
//push new created object to gridData array
$scope.gridData.push(dtArray);
}
};
var onError = function(response) {
console.log("error");
console.log(data);
};
DashboardFactory.getDashboardReportData(dashboardreportid, companyid, companybrandid, startdate, enddate, clientdb, calltype, secondarycallval).then(onSuccess, onError);
//ngGrid options
$scope.filterOptions = {
filterText: "",
useExternalFilter: true
};
$scope.totalServerItems = 0;
$scope.pagingOptions = {
pageSizes: [10, 25, 50, 100],
pageSize: 25,
currentPage: 1
};
$scope.getPagedDataAsync = function (pageSize, page, searchText) {
setTimeout(function () {
if (searchText) {};
$scope.setPagingData($scope.gridData, page, pageSize);
}, 100);
};
$scope.setPagingData = function(data, page, pageSize){
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.gridData = pagedData;
$scope.totalServerItems = data.length;
if (!$scope.$$phase) {
$scope.$apply();
}
};
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage);
$scope.$watch('pagingOptions', function (newVal, oldVal) {
if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.$watch('filterOptions', function (newVal, oldVal) {
if (newVal !== oldVal) {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}
}, true);
$scope.gridOptions = {
data: 'gridData',
showFilter: true,
enablePaging: true,
totalServerItems: 'totalServerItems',
pagingOptions: $scope.pagingOptions,
plugins: [new ngGridCsvExportPlugin(), new ngGridFlexibleHeightPlugin()],
showFooter: true,
jqueryUITheme: true,
filterOptions: $scope.filterOptions
};
},
templateUrl: "dashboard/drilldownTable.html",
}
}
If you find ngGrid not working correctly, try to doing the same thing with ngTasty http://zizzamia.com/ng-tasty/#TableServerSide should be more straightforward, and if you find a problem with that I will be happy to help you.
I am having trouble with a directive. My model updates with data that is being loaded by a http call. Without the call the service the directive works correctly.
I have a directive called validationmessagefor that listens to when a field has been marked to have an error. When it has an error it displays the error message.
The plunker attached Plnkr
How do I get the directive to respond or load correctly against the model when using services to load data?
angular.module('dataApp', ['servicesModule', 'directivesModule'])
.controller('dataCtrl', ['$scope', 'ProcessService', 'ValidationRuleFactory', 'Validator',
function($scope, ValidationRuleFactory, Validator, ProcessService) {
$scope.viewModel = {};
var FormFields = {};
// we would get this from the meta api
ProcessService.getProcessMetaData().then(function(data) {
FormFields = {
Name: "Course",
Fields: [{
type: "text",
Name: "name",
label: "Name",
data: "",
required: true,
ruleSet: "personFirstNameRules"
}, {
type: "text",
Name: "description",
label: "Description",
data: "",
required: true,
ruleSet: "personEmailRules"
}]
};
$scope.viewModel = FormFields;
ProcessService.getProcessRuleData().then(function(data) {
var genericErrorMessages = {
required: 'Required',
minlength: 'value length must be at least %s characters',
maxlength: 'value length must be less than %s characters'
};
var rules = new ValidationRuleFactory(genericErrorMessages);
$scope.viewModel.validationRules = {
personFirstNameRules: [rules.isRequired(), rules.minLength(3)],
personEmailRules: [rules.isRequired(), rules.minLength(3), rules.maxLength(7)]
};
$scope.viewModel.validator = new Validator($scope.viewModel.validationRules);
});
});
var getRuleSetValuesMap = function() {
return {
personFirstNameRules: $scope.viewModel.Fields[0].data,
personEmailRules: $scope.viewModel.Fields[1].data
};
};
$scope.save = function() {
$scope.viewModel.validator.validateAllRules(getRuleSetValuesMap());
if ($scope.viewModel.validator.hasErrors()) {
$scope.viewModel.validator.triggerValidationChanged();
return;
} else {
alert('person saved in!');
}
};
}
]);
The directive to display the custom error message
(function(angular, $) {
angular.module('directivesModule')
.directive('validationMessageFor', [function() {
return {
restrict: 'A',
scope: {eID: '#val'},
link: function(scope, element, attributes) {
//var errorElementId = attributes.validationMessageFor;
attributes.$observe('validationMessageFor', function(value) {
errorElementId = value;
if (!errorElementId) {
return;
}
var areCustomErrorsWatched = false;
var watchRuleChange = function(validationInfo, rule) {
scope.$watch(function() {
return validationInfo.validator.ruleSetHasErrors(validationInfo.ruleSetName, rule.errorCode);
}, showErrorInfoIfNeeded);
};
var watchCustomErrors = function(validationInfo) {
if (!areCustomErrorsWatched && validationInfo && validationInfo.validator) {
areCustomErrorsWatched = true;
var validator = validationInfo.validator;
var rules = validator.validationRules[validationInfo.ruleSetName];
for (var i = 0; i < rules.length; i++) {
watchRuleChange(validationInfo, rules[i]);
}
}
};
// get element for which we are showing error information by id
var errorElement = $("#" + errorElementId);
var errorElementController = angular.element(errorElement).controller('ngModel');
var validatorsController = angular.element(errorElement).controller('validator');
var getValidationInfo = function() {
return validatorsController && validatorsController.validationInfoIsDefined() ? validatorsController.validationInfo : null;
};
var validationChanged = false;
var subscribeToValidationChanged = function() {
if (validatorsController.validationInfoIsDefined()) {
validatorsController.validationInfo.validator.watchValidationChanged(function() {
validationChanged = true;
showErrorInfoIfNeeded();
});
// setup a watch on rule errors if it's not already set
watchCustomErrors(validatorsController.validationInfo);
}
};
var getErrorMessage = function(value) {
var validationInfo = getValidationInfo();
if (!validationInfo) {
return '';
}
var errorMessage = "";
var errors = validationInfo.validator.errors[validationInfo.ruleSetName];
var rules = validationInfo.validator.validationRules[validationInfo.ruleSetName];
for (var errorCode in errors) {
if (errors[errorCode]) {
var errorCodeRule = _.findWhere(rules, {errorCode: errorCode});
if (errorCodeRule) {
errorMessage += errorCodeRule.validate(value).errorMessage;
break;
}
}
}
return errorMessage;
};
var showErrorInfoIfNeeded = function() {
var validationInfo = getValidationInfo();
if (!validationInfo) {
return;
}
var needsAttention = validatorsController.ruleSetHasErrors() && (errorElementController && errorElementController.$dirty || validationChanged);
if (needsAttention) {
// compose and show error message
var errorMessage = getErrorMessage(element.val());
// set and show error message
element.text(errorMessage);
element.show();
} else {
element.hide();
}
};
subscribeToValidationChanged();
if (errorElementController)
{
scope.$watch(function() {
return errorElementController.$dirty;
}, showErrorInfoIfNeeded);
}
scope.$watch(function() {
return validatorsController.validationInfoIsDefined();
}, subscribeToValidationChanged());
});
}
};
}]);
})(angular, $);