firebase - javascript object returning undefined - javascript

I have a firebase set up. here is the structure:
I am having trouble getting the 'newNroomID' value (that is a6QVH, a7LTN etc..).
this value will be use to compare with the other variable value.
I know that in javascript, to access the value of the object it can be done like this:
var card = { king : 'spade', jack: 'diamond', queen: 'heart' }
card.jack = 'diamond'
but it seems different story when it comes with the firebase or surely enough i am missing something. Here is my code.
var pokerRoomsJoin = firebase.database().ref(); // this is how i set it up this block of code is for reading the data only
pokerRoomsJoin.on('value', function(data){
var rID = data.val();
var keys = Object.keys(rID);
var callSet = false;
for (var i = 0 ; i < keys.length; i++) {
var indexOfKeys = keys[i];
var roomMatching = rID[indexOfKeys];
var matchID = roomMatching.newNroomID; // this does not work alwaus give me undefined
console.log('this return :' + matchID + ' WHY!')
console.log(roomMatching)
if(matchID == 'ffe12'){ // 'ffe12' is actually a dynamic value from a paramiter
callSet = true;
}
}
})
and here is the result of the console log:
strangely i am able to access it like this
var matchID = roomMatching.newNroomID // it return a6QVH and a7LTN one at a time inside the loop
only if i set up the ref to :
var pokerRoomsJoin = firebase.database().ref('room-' + roomId);
I've tried searching but seems different from the structure i have . am I having bad data structure? Save me from this misery , thanks in advance!

Let us see the code inside for loop line by line,
1. var indexOfKeys = keys[i];
now indexOfKeys will hold the key room-id
2. var roomMatching = rID[indexOfKeys];
here roomMatching will hold the object
{ 'firebasePushId': { newDealerName: 'b',
...,
}
}
Now
3. var matchID = roomMatching.newNroomID;
This of-course will be undefined because roomMatching has only one
property , firebasePushId.
To access newNroomID , you have to do something like this,
matchID = roomMatching.firebasePushKey.newNroomID .
One way to get firebasePushKeys will be using Object.keys(roomMatching).

Related

Google spreadsheet error TypeError: Cannot read property 'filter' of undefined

I am taking data from a sheet and then converting it to json, so far all good. But when I am trying to take out specific data from arrays but it is making undefined if I get data from array, but when I use raw json data everything works fine
function doGet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Users');
var userData = getUser(ss);
var array = userData.user.filter(function b(e) { return e.id == 11281 });
console.log(array)
}
function getUser(ss){
var usr = {};
var usrArray = [];
var data = ss.getRange(2,1,ss.getLastRow(), ss.getLastColumn()).getValues();
for (var i=0, l=data.length; i<l; i++){
var dataRow = data[i];
var record = {};
record['id'] = dataRow[1];
record['name'] = dataRow[0];
record['profession'] = dataRow[2];
usrArray.push(record);
}
usr.user = usrArray;
var result = JSON.stringify(usr);
return result;
}
ERROR: TypeError: Cannot read property 'filter' of undefined
Error picture
Sheet data picture
If I console log the result directly the it is working fine like this: Output
JSON.stringify returns a string — the getUser function returns a string. And you're trying to read the user property from it which returns undefined.
You could do a JSON.parse in doGet but it's simpler to just return the usr object from getUser.
function getUser(ss) {
const usr = {}
const usrArray = []
// populate usrArray
usr.user = usrArray
return usr
}
And there's another issue. You're setting record['id'] to dataRow[1] but it should be dataRow[0] since id is the first column (This is why the shared screenshot has the name in the id property). You could also refactor the code.
function getUser(ss) {
const data = ss
.getRange(2, 1, ss.getLastRow(), ss.getLastColumn())
.getValues()
const users = data.map((row) => ({
id: row[0],
name: row[1],
profession: row[2],
}))
return {
user: users,
}
}
I would also recommend renaming the user property to users for clarity.

Pass array values as parameter to function and create json data

I have a scenario where I am passing an array of objects to a function in nodejs, but the same is failing with undefined error.
Here is what I have tried :
var object = issues.issues //json data
var outarr=[];
for(var key in object){
outarr.push(object[key].key)
}
console.log(outarr) // array is formed like this : ['a','b','c','d','e']
for(var i =0; i<outarr.length;i++){
jira.findIssue(outarr[i]) //here I am trying to pass the array objects into the loop one by one
.then(function(issue) {
var issue_number = issue.key
var ape = issue.fields.customfield_11442[0].value
var description = issue.fields.summary
var ice = issue.fields.customfield_15890[0].value
var vice = issue.fields.customfield_15891.value
var sor = issue.fields.labels
if (sor.indexOf("testcng") > -1) {
var val = 'yes'
} else {
var val = 'yes'
}
var obj = {};
obj['ape_n'] = ape;
obj['description_n'] = description;
obj['ice_n'] = ice;
obj['vice_n'] = vice;
obj['sor_n'] = val;
var out = {}
var key = item;
out[key] = [];
out[key].push(obj);
console.log(out)
} })
.catch(function(err) {
console.error(err);
});
});
What I am trying to achieve : I want to pass the array values as a parameter which is required by jira.findissue(bassically passing the issue number) one by one and which should again fetch the values and give a combine json output.
How can I pass this array values one by one in this function and also run jira.findissue in loop.
Any help will be great !! :-)
I have taken a look at the code in your question.
To be honest the code you wrote is messy and contains some simple syntax errors.
A good tip is to use a linter to avoid those mistakes.
More info about linters here: https://www.codereadability.com/what-are-javascript-linters/
To output all results in one array you have to define the array outside the scope of the loop.
I cleaned the code a bit up and use some es6 features. I don't know the context of the code but this is what I can make off it:
//map every value the key to outarr
let outarr = issues.issues.map( elm => elm.key);
//Output defined outside the scope of the loop
let output = [];
//looping outarr
outarr.forEach( el => {
jira.findIssue(el).then(issue => {
//creating the issue object
let obj = {
ape_n: issue.fields.customfield_11442[0].value,
description_n: issue.fields.summary,
ice_n: issue.fields.customfield_15890[0].value,
vice_n: issue.fields.customfield_15891.value,
sor_n: issue.fields.labels.indexOf("testcng") > -1 ? "yes" : "yes",
};
//pushing to the output
output[issue.key] = obj;
}).catch(err => {
console.log(err);
});
});
//ouputing the output
console.log(output);
Some more info about es6 features: https://webapplog.com/es6/

Getting count of unsaved records in Indexeddb

I have some records saved in an Indexeddb, One of the fields in my db is "modifieddate". I want to get a count of all the records where modified date is not null.
I can count all records in my database like this:
var request = store.count();
I have tried something like this:
var myIndex = store.index('modifiedDate');
var cts = myIndex.count();
But that doesnt work. Any ideas ?
Getting a count of the index should work. Make sure that you do not set the modifiedDate for objects that were never modified. If the modifiedDate property is undefined, null, or does not exist in the object's set of properties, then the index will not include the object, leading to only objects with a defined modifiedDate property being included in the modifiedDate index, which leads to count returning the property number.
The second problem is how you are using the count function. IDBObjectStore.count and IDBIndex.count return an IDBRequest object, not a number. You have to get the count asynchronously. This can be done easily using a callback function.
var countRequest = myIndex.count();
countRequest.onsuccess = function(event) {
var theActualCountNumber = event.target.result;
// Alternatives to above statement, use whatever you like
// var theActualCountNumber = countRequest.result;
// var theActualCountNumber = this.result;
console.log('Number of objects with a modifiedDate property: ',
theActualCountNumber);
};
You cannot return 'theActualCountNumber' variable value from the callback function. It is only defined and accessible within the function. So, whatever code that wants to use the count value after you have obtained it must be located within the function itself. A simple trick to make the code cleaner and easier to use is the following:
function countModified(db, callback) {
var tx = db.transaction('mystore');
var store = tx.objectStore('mystore');
var index = store.index('modifiedDate');
var request = index.count();
request.onsuccess = function(event) {
var count = event.target.result;
callback(count);
};
}
// An example of how to call it
var openRequest = indexedDB.open('mydb', myversion);
openRequest.onsuccess = function(event) {
var db = event.target.result;
countModified(db, onGetCountModified);
};
function onGetCountModified(count) {
console.log('There are %s modified objects', count);
}

Javascript: loop through array

This is driving me crazy. I'm just trying to print out an array and it's not working. What am I missing? The results variable is returning "undefined" which much mean my for loop isn't working correctly. Everything else works properly, the console.log I have correctly displays the fields are added to the array.
// The list of accounts array.
var accountsArray = [];
function addAccount() {
// Take fields and put user data into varables.
var accountName = document.getElementById('accountName').value;
var accountBalance = document.getElementById('accountBalance').value;
var accountType = document.getElementById("accountType");
var accountTypeSelected = accountType.options[accountType.selectedIndex].text;
var accountCurrency = document.getElementById("accountCurrency");
var accountCurrencySelected = accountCurrency.options[accountCurrency.selectedIndex].text;
// Put these variables into the array.
accountsArray.push(accountName);
accountsArray.push(accountBalance);
accountsArray.push(accountTypeSelected);
accountsArray.push(accountCurrencySelected);
// Items added to the array, logged.
console.log('user added: ' + accountsArray);
}
function accountsListHtml() {
var results;
// Loop through the array
for (var i = 0; i < accountsArray.length; i++) {
results = accountsArray[i];
}
document.getElementById('accountsList').innerHTML = results;
}
Here's a link to all the files. It's an iOS web app using Framework7. Balance Pro
You are calling accountsListHtml() in body.onload. At that point accountsArray is empty.
I can't find any other possibility to call accountsListHtml() on that page you linked to.
Add one line inside function addAccount() and it will work:
function addAccount() {
/* vour code */
console.log('user added: ' + accountsArray);
accountsListHtml(); // add this line
}
Try changing results = accountsArray[i]; to results += accountsArray[i];.
Update
And initialize results with an empty string, for example :)
for (var i = 0; i < accountsArray.length; i++) {
results = accountsArray[i];
}
The statement in the for loop i.e. results = accountsArray[i]; overwrites the variable results evry loop run. You could change the statement to :
results += accountsArray[i].toString();
and initialise results to an empty string.
The following works for me: http://jsfiddle.net/95ztrmk3/13/
HTML:
<div id="accountsList"></div>
JS:
// The list of accounts array.
var accountsArray = [];
addAccount();
accountsListHtml();
function addAccount() {
// Take fields and put user data into varables.
var accountName = "John Doe";
var accountBalance = "500.00";
var accountTypeSelected = "Checking"
var accountCurrencySelected = "USD";
// Put these variables into the array.
accountsArray.push(accountName);
accountsArray.push(accountBalance);
accountsArray.push(accountTypeSelected);
accountsArray.push(accountCurrencySelected);
// Items added to the array, logged.
console.log('user added: ' + accountsArray);
}
function accountsListHtml() {
var results = [];
// Loop through the array
for (var i = 0; i < accountsArray.length; i++) {
results += accountsArray[i] + " ";
}
document.getElementById('accountsList').innerHTML = results;
console.log(results);
}
Assuming the input isn't malformed or otherwise weird. I made sure Javascript recognizes results is an empty array and not a string or something: var results = []

return from JS function

basic JS question, please go easy on me I'm a newb :)
I pass 2 variables to the findRelatedRecords function which queries other related tables and assembles an Array of Objects, called data. Since findRelatedRecords has so many inner functions, I'm having a hard time getting the data Array out of the function.
As it currently is, I call showWin inside findRelatedRecords, but I'd like to change it so that I can get data Array directly out of findRelatedRecords, and not jump to showWin
function findRelatedRecords(features,evtObj){
//first relationship query to find related branches
var selFeat = features
var featObjId = selFeat[0].attributes.OBJECTID_1
var relatedBranch = new esri.tasks.RelationshipQuery();
relatedBranch.outFields = ["*"];
relatedBranch.relationshipId = 1; //fac -to- Branch
relatedBranch.objectIds = [featObjId];
facSel.queryRelatedFeatures(relatedBranch, function(relatedBranches) {
var branchFound = false;
if(relatedBranches.hasOwnProperty(featObjId) == true){
branchFound = true;
var branchSet = relatedBranches[featObjId]
var cmdBranch = dojo.map(branchSet.features, function(feature){
return feature.attributes;
})
}
//regardless of whether a branch is found or not, we have to run the cmdMain relationship query
//the parent is still fac, no advantage of the parent being branch since cmcMain query has to be run regardless
//fac - branch - cmdMain - cmdSub <--sometimes
//fac - cmdMain - cmdSub <-- sometimes
//second relationship query to find related cmdMains
var relatedQuery = new esri.tasks.RelationshipQuery();
relatedQuery.outFields = ["*"];
relatedQuery.relationshipId = 0; //fac -to- cmdMain
relatedQuery.objectIds = [featObjId];
//rather then listen for "OnSelectionComplete" we are using the queryRelatedFeatures callback function
facSel.queryRelatedFeatures(relatedQuery, function(relatedRecords) {
var data = []
//if any cmdMain records were found, relatedRecords object will have a property = to the OBJECTID of the clicked feature
//i.e. if cmdMain records are found, true will be returned; and continue with finding cmdSub records
if(relatedRecords.hasOwnProperty(featObjId) == true){
var fset = relatedRecords[featObjId]
var cmdMain = dojo.map(fset.features, function(feature) {
return feature.attributes;
})
//we need to fill an array with the objectids of the returned cmdMain records
//the length of this list == total number of mainCmd records returned for the clicked facility
objs = []
for (var k in cmdMain){
var o = cmdMain[k];
objs.push(o.OBJECTID)
}
//third relationship query to find records related to cmdMain (cmdSub)
var subQuery = new esri.tasks.RelationshipQuery();
subQuery.outFields = ["*"];
subQuery.relationshipId = 2;
subQuery.objectIds = [objs]
subTbl.queryRelatedFeatures(subQuery, function (subRecords){
//subRecords is an object where each property is the objectid of a cmdMain record
//if a cmdRecord objectid is present in subRecords property, cmdMain has sub records
//we no longer need these objectids, so we'll remove them and put the array into cmdsub
var cmdSub = []
for (id in subRecords){
dojo.forEach(subRecords[id].features, function(rec){
cmdSub.push(rec.attributes)
})
}
var j = cmdSub.length;
var p;
var sub_key;
var obj;
if (branchFound == true){
var p1 = "branch";
obj1 = {};
obj1[p1] = [cmdBranch[0].Branches]
data.push(obj1)
}
for (var i=0, iLen = cmdMain.length; i<iLen; i++) {
p = cmdMain[i].ASGMT_Name
obj = {};
obj[p] = [];
sub_key = cmdMain[i].sub_key;
for (var j=0, jLen=cmdSub.length; j<jLen; j++) {
if (cmdSub[j].sub_key == sub_key) {
obj[p].push(cmdSub[j].Long_Name);
}
}
data.push(obj);
}
showWin(data,evtObj) <---this would go away
})
}
//no returned cmdRecords; cmdData not available
else{
p = "No Data Available"
obj = {}
obj[p] = []
data.push(obj)
}
showWin(data,evtObj) <--this would go away
})
})
}
I'd like to have access to data array simply by calling
function findRelatedRecords(feature,evt){
//code pasted above
}
function newfunct(){
var newData = findRelatedRecords(feature,evt)
console.log(newData)
}
is this possible?
thanks!
Edit
Little more explanation.....
I'm connecting an Object event Listener to a Function like so:
function b (input){
dojo.connect(obj, "onQueryRelatedFeaturesComplete", getData);
obj.queryRelatedFeatures(input);
console.log(arr) //<----this doesn't work
}
function getData(relatedFeatData){
var arr = [];
//populate arr
return arr;
}
So when obj.QueryRelatedFeatures() is complete, getData fires; this part works fine, but how to I access arr from function b ?
Post Edit Update:
Due to the way that this event is being hooked up you can't simple return data from it. Returning will just let Dojo call to the next method that is hooked up to onSelectionComplete.
When init runs it is long before findRelatedRecords will ever be executed/fired by the onSelectionComplete event of the well, which is why you were seeing undefined/null values. The only way to work with this sort of system is to either 1) call off to a method like you're already doing or 2) fire off a custom event/message (technically it's still just calling off to a method).
If you want to make this method easier to work with you should refactor/extract snippets of it to make it a smaller function but contained in many functions. Also, changing it to have only one exit point at the end of the findRelatedRecords method will help. The function defined inside of subTbl.queryRelatedFeatures() would be a great place to start.
Sorry, you're kind of limited by what Dojo gives you in this case.
Pre Edit Answer:
Just return your data out of it. Everywhere where there is a showWin call just use this return.
return {
data: data,
evtObj: evtObj
}
Then your newfunct would look like this.
function newfunct(){
var newData = findRelatedRecords(feature,evt);
console.log(newData);
console.log(newData.data);
console.log(newData.evtObj);
}
If you only need that "data" object, then change your return to just return data;.
Also, start using semicolons to terminate statements.

Categories

Resources