Javascript--Breeze Manager Not Detecting Changes - javascript

I'm using the EntityManager from Breeze for the API portion of data-binding. However, the EntityManager fails to track the changes. It will execute the code like it's supposed to but it never recognizes the changes. What's the issue? Please, refrain from saying anything that is not constructive or any personal attacks. We're here as professionals and scientists(i know i am). Here is my code:
Service:
(function () {
var serviceId = 'UWRLService';
angular.module('myApp')
.factory(serviceId, ['$q', 'breeze', 'logger', 'appSettings', UWRLService]);
// console.log('Initialized UWRL Service.js');
function UWRLService($q, breeze, logger, appSettings) {
// console.log('inside datacontext -- UWRLService');
// configure logging for this service
logger = logger.forSource(serviceId);
var logError = logger.logError;
var logSuccess = logger.logSuccess;
var logWarning = logger.logWarning;
//Setup variables with common Breeze query classes
var entityQuery = breeze.EntityQuery;
// setup breeze entity manager
var serviceName = appSettings.apiUrl + '/breeze/Uwrl/';//Where the entire service is pointing to
var manager = new breeze.EntityManager(serviceName);
var entityStateChangeAction = breeze.EntityAction.EntityStateChange;
// expose methods
var service = {
getChangesCount: getChangesCount,
saveChanges: saveChanges,
rejectChanges: rejectChanges,
getDivisions: getDivisions,
getPools: getPools,
getRandomCust: getRandomCust
//createChangeFactorEntity: createChangeFactorEntity,
};
return service;
// FUNCTION DECLARATIONS
//Attaches a new entity to the Breeze repository
//Passes the name and an array of values to seed the entity with
//function createChangeFactorEntity(entityName, initialValues) {
// var newFactor = manager.createEntity(entityName, initialValues);
// return newFactor;
//}
function getRandomCust()
{
var query = breeze.EntityQuery.from('alpha')
.where('customerNumber', '==', 1);
return executeQuery(query, 'Alpha found!');
}
function getDivisions()
{
var query = breeze.EntityQuery
.from('Divisions');
//executeQuery([query name], [query title])
return executeQuery(query, 'Divisions Found');
}
function getPools()
{
var query = breeze.EntityQuery
.from('Pools');
return executeQuery(query, 'Pools Found');
}
//Saves changes and logs exceptions
function saveChanges() {
var hasChanges = manager.hasChanges();
console.log(hasChanges);
console.log(manager.getChanges());
return manager.saveChanges()
.then(saveSucceeded)
.catch(saveFailed);
function saveSucceeded(saveResult) {
logSuccess("# of items saved = " + saveResult.entities.length, null, true);
logger.log(saveResult);
}
function saveFailed(error) {
var reason = error.message;
var detail = error.detail;
if (error.entityErrors) {
//Do nothing
} else if (detail && detail.ExceptionType &&
detail.ExceptionType.indexOf('OptimisticConcurrencyException') !== -1) {
// Concurrency error
reason =
"Another user, perhaps the server, " +
"may have deleted one or all of the todos." +
" You may have to restart the app.";
} else {
reason = "Failed to save changes: " + reason +
" You may have to restart the app.";
}
logError(reason, error, true);
throw error; //Downstream: users know it has failed
}
}
//Discards changes in Breeze Manager
function rejectChanges() {
if (manager.hasChanges()) {
count = getChangesCount();
manager.rejectChanges();
logWarning('Discarded ' + count + ' pending changes(s)', null, true);
}
}
//Returns (Nth-1) index of Breeze manager getChanges array
function getChangesCount() {
var ents = manager.getEntities();
var changes = manager.getChanges();
if (changes.length > 0)
{
alert("Changes made: " + manager.getChanges().length);
}
return manager.getChanges().length;
}
//Query Execution w/ toasters(logger)
function executeQuery(query, entityType) {
var promise = manager.executeQuery(query).then(querySucceeded, queryFailed);
return promise;
function querySucceeded(response) {
logSuccess(entityType + " query was successful", null, true);
return response.results;
}
function queryFailed(response) {
var message = response.message || entityType + " query failed";
logError(message, response, true);
throw error;
}
}
};
})()
Controller (javascript):
(function () {
'use strict';
var controllerId = 'UWRLController';
// console.log('Initialized UWRLController');
//Last item in passed array is the Controller (specific)
angular.module('myApp').controller(controllerId,
['$scope', 'UWRLService', 'logger',
'$routeParams', 'allStatesService', UWRLController]);
function UWRLController($scope, UWRLService, logger, $routeParams, allStatesService) {
// console.log('inside UWRLController');
//Loggin Initialization
logger = logger.forSource(controllerId);
var logError = logger.logError;
var logSuccess = logger.logSuccess;
var logWarning = logger.logWarning;
var uwrl = {};
$scope.uwrl = uwrl;
//Parameters we pass from Renewal Group Maintenance screen
//uwrl.PlanCode = $routeParams.PlanCode;
//uwrl.Contract = $routeParams.ContractNumber;
//uwrl.Mch = $routeParams.Mch;
//Functions in Javascript Controller
//[scope].[property] = [function name]
uwrl.saveChanges = save;
uwrl.discardChanges = discardChanges;
uwrl.changesCount = changesCount();
//uwrl.select = select;
init();//Initialize all customer related data for page
function init()
{
gettingDivisions();//Initialze getting data from Division's table through UWRL-service.js
getAllFiftyStates();
gettingPools();
gettingRandom();
}
function gettingRandom()
{
UWRLService.getRandomCust()
.then(function(alpha)
{
uwrl.alpha = alpha;
uwrl.beta = uwrl.alpha[0].customerName;
});
}
function gettingDivisions()
{
UWRLService.getDivisions()
.then(function (divisionNumber) {
uwrl.divisionNumber = divisionNumber;
});
}
function getAllFiftyStates()
{
allStatesService.getStates()
.then(function (allStates)
{
uwrl.allStates = allStates;
});
}
function gettingPools()
{
UWRLService.getPools()
.then(function (poolNumber)
{
uwrl.poolNumber = poolNumber;
});
}
//Clicking the Drop-down Button
//function select(change) {
// this.MchMcpPlanDesignId = change.MchMcpPlanDesign.MchMcpPlanDesignId;
// change.expanded = !change.expanded; //toggle back and forth
//}
////.then = [if] success
////.fail = failure
////.finally = always executed despite evaluated conditionals
//function getPlans() {//returns a promise
// uwrl.loadingPlans = true;
// UWRLService.getChangeFactors(uwrl.Mch, uwrl.Contract, uwrl.PlanCode)
// .then(function (deltaChangeFactor) {
// uwrl.deltaChangeFactor = deltaChangeFactor;
// }).finally(function () { uwrl.loadingPlans = false; });
//}
////Returns all data in ChangeFactorType table
//function getChangeFactorTypes() {
// UWRLService.getTypes().then(function (changeFactorTypes) {
// uwrl.changeFactorTypes = changeFactorTypes;
// });
//}
//Clicking on Save Button
function save() {
console.log('Save Button Clicked!');
//Validation -- checks for empty values
//if (uwrl.changeFactorType != null && uwrl.effectiveDate != null &&
// uwrl.changeFactorAmount != null) {
// //Adds a new Breeze Entity for ChangeFactor table in SQL database
// UWRLService.createChangeFactorEntity('ChangeFactor',
// {
// MchMcpPlanDesignId: this.MchMcpPlanDesignId,
// ChangeFactorType: uwrl.changeFactorType,
// EffectiveDate: uwrl.effectiveDate,
// ChangeFactorAmount: uwrl.changeFactorAmount
// });
//}
//Saves to Breeze Manager
//Must hit Art's ESB service -- to be researched
UWRLService.saveChanges();
}
//Gets rid of changes and logs it
function discardChanges() {
console.log('Discard Button Clicked!');
UWRLService.rejectChanges();
}
//Notifies user(s) of changes made that are
//either: savable, discardable
function changesCount() {
// console.log("Changes Made: " + UWRLService.getChangesCount)//for debugging purposes
return UWRLService.getChangesCount;
}
};
})();

The answer is to make sure to effect the model. For example: uwrl.alpha[0].customerName instead of urwl.beta

Related

Invalid Locator error

I tried to rewrite my tests in Page Object style but something goes wrong.
I use Class Tab and this is a part of my code:
var World = require('../support/world.js');
const isAllAjaxRequests = require('../scripts/util').isAllAjaxRequests;
const isElementLocatedAndVisible = require('../scripts/util').isElementLocatedAndVisible;
module.exports.Tab = class Tab {
constructor(data) {
this.name = "Base";
this.locators = {
'nextStepIsLocked': {xpath: '//md-tab-item[#aria-selected="true"]//div[#class="cc-status red"]'},
'isActiveTab': {xpath: '//md-tab-item[#aria-selected="true"]//span[text()="'+ data + '"]'}
}
}
waitForElement(bySelector) {
var driver = World.getDriver();
var self = this;
//var bySelector = self.locators[bySelector];
return driver.wait(isAllAjaxRequests(driver), waitTimeOut).then(() => {
//console.log(bySelector)
return driver.wait(isElementLocatedAndVisible(bySelector), waitTimeOut);
});
}
tabIsOpen(tabName) {
var driver = World.getDriver();
var self = this;
var bySelector = By.xpath('//md-tab-item[#aria-selected="true"]//span[text()="'+ tabName + '"]');
return self.waitForElement(bySelector);
}
}
Code in util:
exports.isElementLocatedAndVisible = function isElementLocatedAndVisible(driver, bySelector) {
return new Condition('element is located and visible', function(driver) {
console.log(bySelector)
return driver.findElements(bySelector).then((arr) => {
if (arr.length > 0) {
return arr[0].isDisplayed();
}
else {
return false;
}
});
});
};
I tried to use is in my test:
this.Then(/^Tab "([^"]*)" is open$/, function (tabName) {
this.createTab(tabName);
//var bySelector = tab.getLocator(isActiveTab);
return tab.tabIsOpen(tabName);
});
But I recieved an Invalid Locator error.
Via debug print I see thah I miss bySelector value when code go to exports.isElementLocatedAndVisible function. This is undefiened.
What I did wrong?
I suspect it is just missing of a parameter causing the issue.
In the following line:
return driver.wait(isElementLocatedAndVisible(bySelector), waitTimeOut);
add driver object as first argument and then bySelector, as follows:
return driver.wait(isElementLocatedAndVisible(driver, bySelector), waitTimeOut);
function is defined as follows:
function isElementLocatedAndVisible(driver, bySelector)
so, expecting driver object along with bySelector

Javascript: Why object is not getting initialise on new api call however the string variable is?

I may be missing something basic as why is it happening.
GET: example.com/users
//gives all data
GET: example.com/users?status=1
//gives data with status = 1
GET: example.com/users // this does not work
gives same data as pervious API condition with status=1
On third hit, self.whereObj is not initialising to default empty object instead it takes previous value of {'status' = '1'}, however self.page and self.limit is taking default value if no query parameter is provided in query string.
example.com/users?limit=3, // takes override to 3 form default value of 5
example.com/users // self.limit takes default 5 and this works fine
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not ?
var Bookshelf = require('../../dbconfig').bookshelf;
Bookshelf.Collection = Bookshelf.Collection.extend({
limit: 5,
page: 1,
whereObj: {}
myFetch: function (query_params,expectedWhereFields) {
var self = this;
var whereObj = self.whereObj ; // this is not initializing
// var whereObj = {}; this is initialising
var page = self.page;
var limit = self.limit; //this is not showing nay initialisation error
for (var x in query_params) {
if (expectedWhereFields.includes(x)) {
whereObj[x] = query_params[x];
}
if (x === 'page') {
page = query_params[x];
}
if (x === 'limit') {
limit = query_params[x];
}
}
var offset = (page - 1) * limit;
function fetch() {
return self.constructor.forge()
.query({where: whereObj})
.query(function (qb) {
qb.offset(offset).limit(limit);
})
.then(function (collection) {
return collection;
})
.catch(function (err) {
return err
});
}
return new fetch();
}
});
module.exports = Bookshelf;
UPDATED
service.js
var Model = require('./../models/Users');
var express = require('express');
var listUsers = function (query_params, callback) {
var expectedWhereFields = ["type", "status", "name"];
Model.Users
.forge()
.myFetch(query_params, expectedWhereFields)
.then(function (collection) {
return callback(null, collection);
})
.catch(function (err) {
return callback(err, null);
});
};
module.exports = {
listUsers: listUsers
};
model/Users.js
var Bookshelf = require('../../dbconfig').bookshelf;
var Base = require('./base');
// Users model
var User = Bookshelf.Model.extend({
tableName: 'user_table'
});
var Users = Bookshelf.Collection.extend({
model: User
});
module.exports = {
User: User,
Users: Users
};
So my question is why the self.limit (simple string variable) is initialising however self.whereObj is not?
Because objects are reference values. When you set var whereObj = self.whereObj;, both refer to the same object, and when you copy the query parameters into the object properties you are effectively writing into your defaults instance. This does not happen with primitive values such as strings - they don't have mutable properties.

Redirect to new page after results are loaded

I am making a small web app that gets information about upcoming events, based on user input. I want to redirect the user to the results page as soon as the data is retrieved and stored in the local storage. Unfortunately, I am having trouble doing that as the user is redirected just before the content from the search is retrieved.
This is the service I am using to get the data from the API.
EventsService
app.service("EventsService", ["$http", function ($http) {
this.searchByCity = function (city) {
return $http.get("http://api.gigatools.com/city.json?cities[]=" + city + "&api_key=d924857077bc386767")
.then(function (response) {
return response.data[1];
})
}
this.searchByArtist = function (artist) {
return $http.get("http://api.gigatools.com//gigs.json?users[]=" + artist + "&api_key=d924857077bc386767")
.then(function (response) {
var allEvents = response.data[1];
var filteredEvents = [];
allEvents.forEach(function (singleEvent) {
if (singleEvent.event_owner === artist) {
filteredEvents.push(singleEvent);
}
})
return filteredEvents;
})
}
this.searchByVenue = function (venue) {
return $http.get("http://api.gigatools.com/venue.json?venues[]=" + venue + "&api_key=d924857077bc386767")
.then(function (response) {
return response.data[1];
})
}}])
This is the search function, that is executed when the user has entered his event preferences and clicked on the search button.
$scope.search = function (input) {
var searching = true;
switch ($scope.selected.id) {
case "city" :
console.log("Have to search by city.");
EventsService.searchByCity(input)
.then(function (events) {
$localStorage.results = events;
searching = false;
console.log($localStorage.results);
})
break;
case "artist" :
console.log("Have to search by artist.");
EventsService.searchByArtist(input)
.then(function (events) {
$scope.results = events;
})
break;
case "venue" :
console.log("Have to search by venue.");
EventsService.searchByVenue(input)
.then(function (events) {
$scope.results = events;
})
break;
}
if (searching === false) {
console.log("Finished.");
windows.location.href("views/ResultsPage.html");
}
}
The resultsPage controller :
var app = angular.module("resultsPage",['ngStorage','ngRoute']);
app.controller ("resultsCtrl",function ($scope,$localStorage) {
var loadResults = function () {
$scope.results = $localStorage.results;
console.log($localStorage.results);
}
loadResults();
})
I am not sure, if this code is enough. Let me know if I should share any other parts of the code.
You are trying to switch from asyncronous context to sycnronous (using "searching" var). In most cases this method has problems.
Instead of it just continue with async flow, like this for example:
$scope.search = function (input) {
var searching = true;
switch ($scope.selected.id) {
case "city" :
console.log("Have to search by city.");
EventsService.searchByCity(input)
.then(saveEvents)
.then(redirectToResultsPage)
break;
// ...
}
// if (searching === false) {
// console.log("Finished.");
// windows.location.href("views/ResultsPage.html");
// }
}
function saveEvents(events) {
$localStorage.results = events;
searching = false;
console.log($localStorage.results);
return $q.when(events); // to chain promises
}
function redirectToResultsPage() {
console.log("Finished.");
windows.location.href("views/ResultsPage.html");
}

Trying to convert existing synchronous XmlHttpRequest object to be asynchronous to keep up with current fads

Soo, I keep getting slammed with cautions from Chrome about how synchronous XmlHttpRequest calls are being deprecated, and I've decided to have a go at trying to convert my use-case over in order to keep up with this fad...
In this case, I have an ~9 year old JS object that has been used as the central (and exemplary) means of transporting data between the server and our web-based applications using synchronous XHR calls. I've created a chopped-down version to post here (by gutting out a lot of sanity, safety and syntax checking):
function GlobalData()
{
this.protocol = "https://";
this.adminPHP = "DataMgmt.php";
this.ajax = false;
this.sessionId = "123456789AB";
this.validSession = true;
this.baseLocation = "http://www.example.com/";
this.loadResult = null;
this.AjaxPrep = function()
{
this.ajax = false;
if (window.XMLHttpRequest) {
try { this.ajax = new XMLHttpRequest(); } catch(e) { this.ajax = false; } }
}
this.FetchData = function (strUrl)
{
if ((typeof strURL=='string') && (strURL.length > 0))
{
if (this.ajax === false)
{
this.AjaxPrep();
if (this.ajax === false) { alert('Unable to initialise AJAX!'); return ""; }
}
strURL = strURL.replace("http://",this.protocol); // We'll only ask for data from secure (encrypted-channel) locations...
if (strURL.indexOf(this.protocol) < 0) strURL = this.protocol + this.adminPHP + strURL;
strURL += ((strURL.indexOf('?')>= 0) ? '&' : '?') + 'dynamicdata=' + Math.floor(Math.random() * this.sessionId);
if (this.validSession) strURL += "&sessionId=" + this.sessionId;
this.ajax.open("GET", strURL, false);
this.ajax.send();
if (this.ajax.status==200) strResult = this.ajax.responseText;
else alert("There was an error attempting to communicate with the server!\r\n\r\n(" + this.ajax.status + ") " + strURL);
if (strResult == "result = \"No valid Session information was provided.\";")
{
alert('Your session is no longer valid!');
window.location.href = this.baseLocation;
}
}
else console.log('Invalid data was passed to the Global.FetchData() function. [Ajax.obj.js line 62]');
return strResult;
}
this.LoadData = function(strURL)
{
var s = this.FetchData(strURL);
if ((s.length>0) && (s.indexOf('unction adminPHP()')>0))
{
try
{
s += "\r\nGlobal.loadResult = new adminPHP();";
eval(s);
if ((typeof Global.loadResult=='object') && (typeof Global.loadResult.get=='function')) return Global.loadResult;
} catch(e) { Global.Log("[AjaxObj.js] Error on Line 112: " + e.message); }
}
if ( (typeof s=='string') && (s.trim().length<4) )
s = new (function() { this.rowCount = function() { return -1; }; this.success = false; });
return s;
}
}
var Global = new GlobalData();
This "Global" object is referenced literally hundreds of times across 10's of thousands of lines code as so:
// Sample data request...
var myData = Global.LoadData("?fn=fetchCustomerData&sortByFields=lastName,firstName&sortOrder=asc");
if ((myData.success && (myData.rowCount()>0))
{
// Do Stuff...
// (typically build and populate a form, input control
// or table with the data)
}
The server side API is designed to handle all of the myriad kinds of requests encountered, and, in each case, to perform whatever magic is necessary to return the data sought by the calling function. A sample of the plain-text response to a query follows (the API turns the result(s) from any SQL query into this format automatically; adjusting the fields and data to reflect the retrieved data on the fly; the sample data below has been anonymized;):
/* Sample return result (plain text) from server:
function adminPHP()
{
var base = new DataInterchangeBase();
this.success = true;
this.colName = function(idNo) { return base.colName(idNo); }
this.addRow = function(arrRow) { base.addRow(arrRow); }
this.get = function(cellId,rowId) { return base.getByAbsPos(cellId,rowId); }
this.getById = function(cellId,rowId) { return base.getByIdVal(cellId,rowId); }
this.colExists = function(colName) { return ((typeof colName=='string') && (colName.length>0)) ? base.findCellId(colName) : -1; }
base.addCols( [ 'id','email','firstName','lastName','namePrefix','nameSuffix','phoneNbr','companyName' ] );
this.id = function(rowId) { return base.getByAbsPos(0,rowId); }
this.email = function(rowId) { return base.getByAbsPos(1,rowId); }
this.firstName = function(rowId) { return base.getByAbsPos(2,rowId); }
this.lastName = function(rowId) { return base.getByAbsPos(3,rowId); }
this.longName = function(rowId) { return base.getByAbsPos(5,rowId); }
this.namePrefix = function(rowId) { return base.getByAbsPos(6,rowId); }
this.nameSuffix = function(rowId) { return base.getByAbsPos(7,rowId); }
this.companyName = function(rowId) { return base.getByAbsPos(13,rowId); }
base.addRow( [ "2","biff#nexuscons.com","biff","broccoli","Mr.","PhD","5557891234","Nexus Consulting",null ] );
base.addRow( [ "15","happy#daysrhere.uk","joseph","chromebottom","Mr.","","5554323456","Retirement Planning Co.",null ] );
base.addRow( [ "51","michael#sunrisetravel.com","mike","dolittle","Mr.","",""5552461357","SunRise Travel",null ] );
base.addRow( [ "54","info#lumoxchemical.au","patricia","foxtrot","Mrs,","","5559876543","Lumox Chem Supplies",null ] );
this.query = function() { return " SELECT `u`.* FROM `users` AS `u` WHERE (`deleted`=0) ORDER BY `u`.`lastName` ASC, `u`.`firstName` LIMIT 4"; }
this.url = function() { return "https://www.example.com/DataMgmt.php?fn=fetchCustomerData&sortByFields=lastName,firstName&sortOrder=asc&dynamicdata=13647037920&sessionId=123456789AB\"; }
this.rowCount = function() { return base.rows.length; }
this.colCount = function() { return base.cols.length; }
this.getBase = function() { return base; }
}
*/
In virtually every instance where this code is called, the calling function cannot perform its work until it receives all of the data from the request in the object form that it expects.
So, I've read a bunch of stuff about performing the asynchronous calls, and the necessity to invoke a call-back function that's notified when the data is ready, but I'm a loss as to figuring out a way to return the resultant data back to the original (calling) function that's waiting for it without having to visit every one of those hundreds of instances and make major changes in every one (i.e. change the calling code to expect a call-back function as the result instead of the expected data and act accordingly; times 100's of instances...)
Sooo, any guidance, help or suggestions on how to proceed would be greatly appreciated!

Can't use Angular $q library in Visual Studio (Apache cordova)

I need to use $q to wait until my async function has completed and then do something.
However I have tried injecting $q into my angular module as well as my angular functions and I am getting the message $q is undefined.
Can someone tell me how I can go about being able to use this in my code?
Here is the code for the module and the function I want to use $q in respectively
Module
var droidSync = angular.module('droidSync', ['ionic', 'ngRoute', 'ui.router']);
Controller and FunctionIn this case I want to wait for the results.forEach to finish then I want to hide my loading screen using $ionicLoading.hide()
droidSync.controller('mainController', function ($scope, $ionicLoading) {
$scope.syncContacts = function () {
//Display a loading screen while sync is in execution
$ionicLoading.show({
template: '<p>Syncing Contacts...</p><ion-spinner class="spinner-calm" icon="crescent"/>'
});
var table = AzureService.getTable('contact');
table.read().done(function (results) {
results.forEach(function (result) { //THIS NEEDS TO BE COMPLETE BEFORE HIDING LOAD SCREEN
console.log('result is', result);
// If the contact is flagged as deleted check if its on the device and delete it
if (result.isdeleted == true) {
var options = new ContactFindOptions();
options.filter = result.id;
options.multiple = false;
var fields = ["*"];
navigator.contacts.find(fields, findSuccess, findError, options);
function findSuccess(contact) {
if (contact.length > 0) {
console.log("inside the delete area:", contact);
var contactToDelete = navigator.contacts.create();
//It is safe to use contact[0] as there will only ever be one returned as AzureID is unique
contactToDelete.id = contact[0].id;
contactToDelete.rawId = contact[0].id;
console.log('we want to delete this', contactToDelete);
contactToDelete.remove();
console.log('Contact Deleted');
}
else {
console.log('Contact to delete not present on device. Checking next contact');
}
}
function findError() {
console.log('Contact search failed: Deleted Contact Search');
}
}
else {
//create a contact object to save or update
var emails = [];
var phoneNumbers = [];
var name = new ContactName();
var contactToUpdate = navigator.contacts.create();
contactToUpdate.note = result.id;
name.givenName = result.firstname;
name.familyName = result.lastname;
phoneNumbers[0] = new ContactField('mobile', result.mobilephone, true);
phoneNumbers[1] = new ContactField('home', result.homephone, false);
emails[0] = new ContactField('work', result.email, true);
contactToUpdate.name = name;
contactToUpdate.phoneNumbers = phoneNumbers;
contactToUpdate.emails = emails;
//Search for the contact on the device
var options = new ContactFindOptions();
options.filter = result.id;
options.multiple = false;
var fields = ["*"];
navigator.contacts.find(fields, foundSuccess, foundError, options);
function foundSuccess(contact) {
if (contact.length > 0) {
//The contact has been found on the device. Pass in ids for contact, emails and phone numbers to update.
console.log('object to update is object is', contact);
console.log('contact array length is ', contact.length);
contactToUpdate.id = contact[0].id;
contactToUpdate.rawId = contact[0].rawId;
contactToUpdate.phoneNumbers[0].id = contact[0].phoneNumbers[0].id;
contactToUpdate.phoneNumbers[1].id = contact[0].phoneNumbers[1].id;
contactToUpdate.emails[0].id = contact[0].emails[0].id;
console.log('about to save this', contactToUpdate);
contactToUpdate.save(upSuccess, upError);
function upSuccess() {
console.log('updated a contact!');
}
function upError(ContactError) {
console.log('error updating a contact!');
}
}
else {
//The contact does not exist on the device. Just save it.
console.log('non existent contact: ', contactToUpdate);
contactToUpdate.save(saveSuccess, SaveError);
function saveSuccess() {
console.log('saved a contact!');
}
function SaveError() {
console.log('error saving a contact!');
}
}
}
function foundError() {
console.log('Contact search failed: Undeleted Contact Search');
}
} // end else
})) // end forEach
}) // table.read()
}; // scope.syncContacts()
});
So i'd probably do something like this
This is completely untested code so take that for what you will
$q.all is what your going to want to look into
droidSync.controller('mainController', ["$scope", "$q", "$ionicLoading",
function ($scope, $q, $ionicLoading) {
var loop = function(result){
var deferred = $q.defer();
deferred.resolve(// your loop stuff);
return deferred.promise;
};
var loopingFunction = function(results){
var promises = [];
results.forEach(function(result){
promises.push(loop(result));
});
return $q.all(promises);
};
$scope.syncContacts = function () {
//Display a loading screen while sync is in execution
$ionicLoading.show({
template: '<p>Syncing Contacts...</p><ion-spinner class="spinner-calm" icon="crescent"/>'
});
var table = AzureService.getTable('contact');
table.read().done(function (results) {
loopingFunction(results).then(function(){
// do something after it finishes
$ionicLoading.hide()
});
});
};
}]);

Categories

Resources