Populate dynamic arrays with elements using AngularJS and JS - javascript

I have a cross platform app developed using AngularJS, Monaca and Onsen UI.
I have a service that gets and sets values to be access from various controllers throughout the app.
I have various SQLite database tables created already and each one populated with values. What I need to do is access the tables and store the table values in their "corresponding" arrays in order for them to be accessible from the apps views.
First, I initialise the arrays to store the values that will be retrieved from the database tables. Then I create the table-array association JSON which will match the array to be populated with its corresponding table as the small extract shows below.
// Init Arrays and Table association
var FruitArray = [];
var VegArray = [];
var formArrays = [{
tablename: "tb_fruit",
arrayname: "FruitArray"
}, {
tablename: "tb_veg",
arrayname: "VegArray"
}];
Next, I query the SQLite tables and used the retrieved values to populate the arrays as the sample below shows.
var myFunctions = {
initFormData: function () {
for (var i = 0; i < formArrays.length; i++) {
myFunctions.queryTable(formArrays[i].tablename, formArrays[i].arrayname);
}
},
// Query the Tables
queryTable: function (tableName, arrayName) {
var sql = 'SELECT * FROM ' + tableName;
db.transaction(function (tx) {
tx.executeSql(sql, [],
(function (arrayName) {
return function (tx, results) {
myFunctions.querySuccess(tx, results, arrayName);
};
})(arrayName), myFunctions.queryError);
});
},
So far s good. In my success callback below I try and push the data retrieved from the table to the array - but with no luck. I have done something similar previously but adding data to arrays in AngularJS ala. $scope[arrayName].push(results.rows.item(i)). But I cant seem to do the same in this case.
// Success Callback
querySuccess: function (tx, results, arrayName) {
for (var i = 0; i < results.rows.length; i++) {
alert("Array Name: " + arrayName + // Working - returns name e.g. VegArray
"\n Results: " + results.rows.item(i)); // Working - returns [object Object]
[arrayName].push(results.rows.item(i));
alert("Array: " + [arrayName]); // Not working here - simply returns name e.g. VegArray
}
},
// Error Callback
queryError: function (tx, err) {
alert("An error has occured);
},
} // myFunctions() end
return myFunctions;
How do I push the values from my tables to the arrays? Is this the best method (guessing no) or is there a better way (guessing yes).

Related

Executing mysql queries sequentially nodejs

I am pretty new to nodejs and am using it to construct an api with a mysql database and have run into an issue where I am unable to execute mysql queries sequentially.
The database structure is that there are three tables. Table a in a one to many relation with table b, which is in a one to many relation with table c.
I need a GET endpoint where aid is given and it returns a result with an array of items of b with the array of items of c nested inside it.
Sample Result:
{
logcode: "",
logmessage: "",
bitems: [{
bitemid: 1
citems: [{
citemid: 1
} {
citemid: 2
}]
}{
bitemid: 2
citems: [{
citemid: 3
}]
}]
}
Currently I am attempting to do this by first executing a query where I retrieve all the values of type b that correspond to the received key of entity a and then running a foreach loop over the results and extracting the bitem ids and then running another query within the foreach loop to get all items of table c with that specific foreign key.
async function (req, res) {
let functionname = 'getAllItems'
const conLocalPool = db.conLocalPool.promise();
var data = {}
const atoken = req.get('token');
var str = ``;
str = `call ${functionname}('${atoken}')`;
console.log(str);
try {
const [rows, fields] = await conLocalPool.query(str)
data = rows[0][0]
if (data.logcode === 20100) {
data.bitems = rows[1];
data.bitems.forEach(async (bitem) => {
var stmt = `Select * from \`table-c\` where bitemid=${bitem.id}`
try {
const [citemrows, citemfields] = await conLocalPool.query(stmt);
console.log(citemrows[1])
bitem.citems = citemrows[1];
return true;
}
catch (err) {
console.log(err);
return false;
}
})
}
res.status(200).send(data);
return true;
}
catch (err) {
res.status(500).send({
error: err.message
});
return false;
}
}
Using this function, I am able to get a response which contains all the bitems related to the aitemtoken but without the citems related to each individual bitem.
I would like some help on how to execute the first query and then the later queries based on the response that it retrieves.
According to your last comment, I'm sure that you can achieve it by doing JOIN. There are a few ways to do it but consider this example below:
SELECT * FROM owner o
JOIN dogs d ON o.id=d.owner_id
JOIN dog_toys t ON d.id=t.dog_id
WHERE o.id=1;
Assuming that you have 3 tables (owner, dogs & dog_toys) and each of the table have a relation of owner.id=dogs.owner_id and dogs.id=dog_toys.dog_id, you can simply JOIN all three of them in one query and modify the returned results in SELECT.
I've created a sample fiddle here : https://www.db-fiddle.com/f/ukBgL4M3NzkyTDC6nMGkJn/1

How to load into an array all objects after Query Parse.com

I'm using Parse.com as my backend and after Query how can I fill an array with all the data inside the Parse object? how can I avoid re-mapping? example:
$scope.addContList = contacts.map(function(obj) { // re-map!!!!
return {name: obj.get("name")}; // mapping object using obj.get()
});
I'm mapping my Parse object's properties one by one: name: obj.get("name"), etc. is there a better way?
$scope.addContList = [];
var ActivityContact = Parse.Object.extend("ActivityContact2");
var query = new Parse.Query(ActivityContact);
query.equalTo("activityId", $scope.objId);
query.find({
success: function(contacts) {
console.log("Successfully retrieved " + contacts.length + " contact.");
$scope.$apply(function() {
/*$scope.addContList = contacts.map(function(obj) {
return {name: obj.get("name")}; // mapping object using obj.get()
});*/
for (var i = 0; i < contacts.length; i++) {
$scope.addContList.push(contacts.ALL_PROPERTIES); // contacts.ALL_PROPERTIES does not exist, I'm looking a way to do that and avoid mapping?
}
});
console.log("--->>>"+JSON.stringify($scope.addContList, null, 4));
},
error: function(object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
Should I use Underscore library, is that the only way to go?
I have seen some ppl using PFQuery but I don't know what is that, is PFQuery better for this?
Thanks!
The other answers are correct, but I think it's unnecessary to launch a digest cycle every time you add an item from contacts to $scope.addContList. Something like this should be sufficient:
query.find({
success: function (contacts) {
$scope.apply(function () {
// 1) shallow-copy the list of contacts...
// (this is essentially what you are trying to do now)
$scope.addContList = contacts.slice();
// or 2) just assign the reference directly
$scope.addContList = contacts;
// or 3) transform the Parse.Object instances into
// plain JavaScript objects
$scope.addContList = contacts.map(function (c) {
return c.toJSON();
});
});
},
error: function (object, error) {
// The object was not retrieved successfully.
// error is a Parse.Error with an error code and message.
}
});
Options 1) and 2) will correspond to a template similar to
<div ng-repeat="cont in addContList">{{ cont.get('name') }}</div>
while option 3) can be used like
<div ng-repeat="cont in addContList">{{ cont.name }}</div>
If you change
$scope.addContList = contacts[i];
to:
$scope.addContList.push(contacts[i]);
you should be good to go. Your previous code was re-assigning addContList to be each element in the contacts array, instead of adding the element to it. So at the end of your for loop, $scope.addContList would just be the last contact in your contacts array.
Change:
$scope.addContList = contacts[i];
to
$scope.addContList.push(contacts[i]);

Using nodejs to parse JSON

So, I'm using nodejs to parse json, and I'm wanting to get an object that's an array and use the values in a for each loop.
JSON I'm getting: http://tmi.twitch.tv/group/user/loneztar/chatters
var cronUsers = client.utils.cronjobs('1 * * * * *', function() {
console.log('API Test');
console.log('Response from Twitch Chat:');
request('http://tmi.twitch.tv/group/user/loneztar/chatters', function (error, response, body) {
if (!error && response.statusCode == 200) {
data = JSON.parse(body);
console.log(data.chatters.viewers);
//for each string in the viewers
}
})
});
Above is the code I'm using to retrieve the data. And when I log to the console I get the following (at time of asking):
[ 'duckziller72',
'adanaran',
'nyckeln',
'diabolicalsheep69',
'audery101',
'gone_nutty',
'k4unl',
'eidokan',
'mattesolo',
'siland',
'nullvoid8',
'troy00114',
'sixdev',
'jake_evans',
'doctoranguus',
'juicegraip',
'k4rush' ]
Now I want to use each of them strings in a for each loop. I've tried using the data var I'm using but I can't get anything working. Would appreciate some help! Feel free to ask for other stuff, I'll happily edit.
There are a few different ways to do this.
Using a loop counter:
var viewers = data.chatters.viewers;
var numViewers = viewers.length;
for (var i = 0; i < numViewers; i++) {
var viewer = viewers[i];
console.log(viewer);
}
Using 'for .. in':
var viewers = data.chatters.viewers;
for (var i in viewers) {
var viewer = viewers[i];
console.log(viewer);
}
You may have been trying to use this, but the loop variable contains the indices of the array, not the values.
Using Array.prototype.forEach():
data.chatters.viewers.forEach(function(viewer) {
console.log(viewer);
});
Note that none of this is specific to Node.js or JSON responses.

Integrating a link to my database within the Win 8 App Search Contract

In my Win 8 app, based on a blank template, I have successfully added search contract and it seems to work despite the fact that I have not linked it to any data yet, so, for now, when I search any term in my app it simply takes me to the searchResults page with the message "No Results Found" this is what I was expecting initially.
Now what I wish to do is link my database into the searchResults.js file so that I can query my database. Now outside of the search contract I have tested and connected my Db and it works; I did this using WinJS.xhr, to connect to my web-service which in turn queries my database and returns a JSON object.
In my test I only hardcoded the url, however I now need to do two things. Move the test WinJS.xr data for connecting my DB into the search contract code, and second - change the hardcoded url to a dynamic url that accepts the users search term.
From what I understand of Win 8 search so far the actual data querying part of the search contract is as follows:
// This function populates a WinJS.Binding.List with search results for the provided query.
_searchData: function (queryText) {
var originalResults;
// TODO: Perform the appropriate search on your data.
if (window.Data) {
originalResults = Data.items.createFiltered(function (item) {
return (item.termName.indexOf(queryText) >= 0 || item.termID.indexOf(queryText) >= 0 || item.definition.indexOf(queryText) >= 0);
});
} else {`enter code here`
originalResults = new WinJS.Binding.List();
}
return originalResults;
}
});
The code that I need to transfer into this section is as below; now I have to admit I do not currently understand the code block above and have not found a good resource for breaking it down line by line. If someone can help though it will be truly awesome! My code below, I basically want to integrate it and then make searchString be equal to the users search term.
var testTerm = document.getElementById("definition");
var testDef = document.getElementById("description");
var searchString = 2;
var searchFormat = 'JSON';
var searchurl = 'http://www.xxx.com/web-service.php?termID=' + searchString +'&format='+searchFormat;
WinJS.xhr({url: searchurl})
.done(function fulfilled(result)
{
//Show Terms
var searchTerm = JSON.parse(result.responseText);
// var terms is the key of the object (terms) on each iteration of the loop the var terms is assigned the name of the object key
// and the if stament is evaluated
for (terms in searchTerm) {
//terms will find key "terms"
var termName = searchTerm.terms[0].term.termName;
var termdefinition = searchTerm.terms[0].term.definition;
//WinJS.Binding.processAll(termDef, termdefinition);
testTerm.innerText = termName;
testDef.innerText = termdefinition;
}
},
function error(result) {
testDef.innerHTML = "Got Error: " + result.statusText;
},
function progress(result) {
testDef.innerText = "Ready state is " + result.readyState;
});
I will try to provide some explanation for the snippet that you didn't quite understand. I believe the code you had above is coming from the default code added by Visual Studio. Please see explanation as comments in line.
/**
* This function populates a WinJS.Binding.List with search results
* for the provided query by applying the a filter on the data source
* #param {String} queryText - the search query acquired from the Search Charm
* #return {WinJS.Binding.List} the filtered result of your search query.
*/
_searchData: function (queryText) {
var originalResults;
// window.Data is the data source of the List View
// window.Data is an object defined in YourProject/js/data.js
// at line 16 WinJS.Namespace.defineļ¼ˆ"Data" ...
// Data.items is a array that's being grouped by functions in data.js
if (window.Data) {
// apply a filter to filter the data source
// if you have your own search algorithm,
// you should replace below code with your code
originalResults = Data.items.createFiltered(function (item) {
return (item.termName.indexOf(queryText) >= 0 ||
item.termID.indexOf(queryText) >= 0 ||
item.definition.indexOf(queryText) >= 0);
});
} else {
// if there is no data source, then we return an empty WinJS.Binding.List
// such that the view can be populated with 0 result
originalResults = new WinJS.Binding.List();
}
return originalResults;
}
Since you are thinking about doing the search on your own web service, then you can always make your _searchData function async and make your view waiting on the search result being returned from your web service.
_searchData: function(queryText) {
var dfd = new $.Deferred();
// make a xhr call to your service with queryText
WinJS.xhr({
url: your_service_url,
data: queryText.toLowerCase()
}).done(function (response) {
var result = parseResultArrayFromResponse(response);
var resultBindingList = WinJS.Binding.List(result);
dfd.resolve(result)
}).fail(function (response) {
var error = parseErrorFromResponse(response);
var emptyResult = WinJS.Binding.List();
dfd.reject(emptyResult, error);
});
return dfd.promise();
}
...
// whoever calls searchData would need to asynchronously deal with the service response.
_searchData(queryText).done(function (resultBindingList) {
//TODO: Display the result with resultBindingList by binding the data to view
}).fail(function (resultBindingList, error) {
//TODO: proper error handling
});

Returning array from javascript class method to a script

I'm building a javascript application using object oriented techniques and I'm running into a problem that I hope someone here can help me resolve.
The following method is designed to return an array populated with rows of data from a web SQL database:
retrieveAllStoreSearches : function(){
this.db.transaction(
function(transaction){
transaction.executeSql(
"SELECT name,store,address FROM searchResults ORDER BY name ASC",
[],
function(transaction, results){
var returnArr = [];
for(var i = 0; i < results.rows.length; i++){
var row = results.rows.item(i);
returnArr.push(row.name + ' | ' + row.address);
}
console.log('Length of returnArr: ' + returnArr.length);
console.log(returnArr);
return returnArr;
},
this.errorHandler
);
}
);
}
This works exactly as expected when logging the results to the console BUT when I try to call the method in the following snippet (located in a different script - which initialises all objects and is responsible for building the application DOM structure and functionality)
console.log(db.retrieveAllStoreSearches());
undefined is returned.
I can't figure out what I am doing wrong as when I have used return in a method to allow an object to be accessed from one class and into a different script I have never encountered any problems.
Could anyone provide any pointers on what I might be doing wrong?
Cannot be done, if your function is calling an asynchronous function, the only way to return results is through a callback. That's the whole point of asynchronous functions, the rest of the code can keep going before the call is finished. It's a different way of thinking about returning values (without blocking the rest of your code).
So you'd have to change your code to the following (plus proper error handling)
retrieveAllStoreSearches : function(callback){
this.db.transaction(
function(transaction){
transaction.executeSql(
"SELECT name,store,address FROM searchResults ORDER BY name ASC",
[],
function(transaction, results){
var returnArr = [];
for(var i = 0; i < results.rows.length; i++){
var row = results.rows.item(i);
returnArr.push(row.name + ' | ' + row.address);
}
callback( returnArr );
},
this.errorHandler
);
}
);
}
Then you can use console.log like the following
db.retrieveAllStoreSearches(function(records) {
console.log(records )
});

Categories

Resources