I'm using firebase to collect data, and i'd like to create a temporary webpage to quickly see the json database (and share it) while testing.
The data is grouped by a date string then the with a random key and then the data. Eg:
{
"20160304" : {
"-KC-aOwSWpt4dlYmjJE4" : {
"coordinates" : "-37.7811465912404, 145.005993055861",
"event" : "Test event",
"time" : "2016-03-04 07:48:43 +0000"
}, etc...
To test showing the event data I'm using javascript in the html as follows:
var myFirebaseRef = new Firebase("https://xxxx.firebaseio.com/");
myFirebaseRef.orderByKey().on("value", function(snapshot) {
snapshot.forEach(function(snapshot) {
console.log("The " + snapshot.key() + " event is " + snapshot.val().event);
});
});
But it only returns
The 20160304 event is undefined
The 20160305 event is undefined
Does anyone know how I can grab the event string?
You're trying to skip a level in your JSON:
<date>
<pushid>
coordinates: ...
event: ...
time: ...
Since you're listening on the root if this structure, your snapshot.forEach() loops over the dates. That means that you still need to loop over the push ids:
var myFirebaseRef = new Firebase("https://xxxx.firebaseio.com/");
myFirebaseRef.orderByKey().on("value", function(snapshot) {
snapshot.forEach(function(snapshot) {
var events = snapshot.val();
Object.keys(events).forEach(function(key) {
console.log(events[key]);
});
});
});
If on the other hand you only want to cater for one event per day, you should store them without the pushid level in there.
Related
I am new in this field. I see there are many ways on the internet and most of them is about the old version of Firebase, like using push(), update(), save(). So, I really don't know how to update it. I tried that like this:
function writeNewEvent(eObj) {
// A post entry.
var userObj = authObj.$getAuth();
// Get a key for a new Post.
var newEventKey = ref.child('events').child(userObj.uid).push().key;
// Write the new post's data simultaneously in the posts list and the user's post list.
var updates = {};
updates['/events/' + userObj.uid+ '/' + newEventKey] = userObj;
return ref.update(updates);
}
But the error is:
angular.js:13920 Error: Firebase.update failed: First argument contains an invalid key ($d) in property 'events.LRnkjDgEu1QtuvUTazTwyms4U063.-KW56c87MThrK0PZp-XH.f'. Keys must be non-empty strings and can't contain ".", "#", "$", "/", "[", or "]"
Could you tell me if my method is correct? And how to implement this function.
It looks like you have an ID so you don't need to use push(), just set() at the id like:
// assuming your input looks somthing like:
let eObj = {
"uuid": "98765-8765-1234567890-7890",
"some-data": "stuff",
"other-data": "other stuff",
"numeric-data": 12345
}
function writeNewEventUsingObjUuid(eObj) {
// A post entry.
var userObj = authObj.$getAuth();
return ref.child('events').child(userObj.uid).set(eObj).then(function () {
console.log('Event added with ID: ' + userObj.uid);
}).catch(function (e) {
console.log('Error adding event: ' + e.message);
});
}
If you really want to use push(), firebase will assign you an ID. Note that an empty push() like you had returns a thenable reference. The work is still done asynchronously event though you get an ID upfront.
I have the following db structure in firebase
I'm trying to grab data that belongs to a specific user id (uid). The documentation has the following example:
firebase.database().ref('/users/' + userId).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
But how can I retrieve data from my example without knowing the unique key for each object?
Update:
I tried a new approach by adding the user id as the main key and each child object has it's own unique id.
Now the challenge is how to get the value of "title".
firebase.database().ref('/tasks/').orderByChild('uid').equalTo(userUID)
Well that is pretty straightforward. Then you can use it like this:
return firebase.database().ref('/tasks/').orderByChild('uid').equalTo(userUID).once('value').then(function(snapshot) {
var username = snapshot.val().username;
// ...
});
Of course you need to set userUID.
It is query with some filtering. More on Retrieve Data - Firebase doc
Edit: Solution for new challenge is:
var ref = firebase.database().ref('/tasks/' + userUID);
//I am doing a child based listener, but you can use .once('value')...
ref.on('child_added', function(data) {
//data.key will be like -KPmraap79lz41FpWqLI
addNewTaskView(data.key, data.val().title);
});
ref.on('child_changed', function(data) {
updateTaskView(data.key, data.val().title);
});
ref.on('child_removed', function(data) {
removeTaskView(data.key, data.val().title);
});
Note that this is just an example.
I am using firebase(angularfire) in my angularjs app to store and process my message system but can't seem to figure out how to replicate the example data from the firebase docs
// room members are easily accessible (or restricted)
// we also store these by room ID
"members": {
// we'll talk about indices like this below
"one": {
"mchen": true,
"hmadi": true
}
}
Here the members.one contains the user name as a key and I am trying to do this for my data as well but can't seem to figure out a solution.
The members portion of my firebase data is like so:
members { one: { } }
I have two variables set in the $scope.
user_name = kep; //person chatting with name
sender_name = pek; //current user name
So I want to use the set function to insert data into members.one or in this case members.user_name + ':' + sender_name but where I am having trouble is how to actually insert the data without creating a parent object.
ref.child('members').child(user_name + ':' + sender_name).set({
user_name: true, sender_name: true
});
The problem arises when I try to pass user_name and sender_name into the set() function below is the result it gets.
members { "kep:pek": { user_name: true, sender_name: true }}
where as I want it to be:
members { "kep:pek": { kep: true, pek: true }}
If I put user_name and sender_name into an object and then run the set() function with the object passed it will create the following structure which is not what I am looking for:
members { "kep:pek": { newObject: { kep: true, pek: true }}}
Firebase team member here.
The Firebase Database is a just a JSON document.
So let's say you want to structure your data this way:
{
"members" : {
"kep:pek" : {
"kep" : true,
"pek" : true
}
}
}
A custom key is created by using the .child() method, or by creating a key in the JavaScript Object.
JSBin Demo
var rootRef = new Firebase('<my-firebase-app>');
var membersRef = rootRef.child('members');
var user_name = 'kep';
var sender_name = 'pek';
// child object to store custom keys
var objectToSave = {};
// set keys in [] syntax
objectToSave[user_name] = true;
objectToSave[sender_name] = true;
// use .child() with a formatted string to save the object
membersRef.child(user_name + ':' + sender_name).set(objectToSave);
I am working on an app to store data offline. My problem is when I try to retrieve the data from local storage for update/edit, it keeps calling only the id of the first item, and not calling the id of the data in view.
Please what am I doing wrong?
Here is my code for loading employees:
// load cases from localStorage
var employees;
if (localStorage.getItem('employees')) {
employees = JSON.parse(localStorage.getItem('employees'));
} else {
// If no cases, create and save them
employees = [];
// offling storing of our cases
localStorage.setItem('employees', JSON.stringify(employees));
}
// show case listing in list view page
var showEmployees = function () {
//erase existing content
$('#employee_list').html('');
//insert each employee
for (var i = 0; i<employees.length; i++) {
addEmployees(employees[i]);
}
};
Here is my code to add an employee to list view:
//add an eliment to list view
var addEmployees = function (empData) {
//HTML content of one list element
var listElementHTML = '<li><a class="employee_list" ui-btn ui-btn-e ui-btn-icon-right ui-icon-carat-r" data-transition="fade" data-split-icon="delete" href="#item'+empData.id+'">' + empData.employeename + '<br> ' + empData.dateofbirth + '</br></a></li>';
//appending the HTML code to list view
$('#employee_list').append(listElementHTML);
};
Here is my code for Edit function:
//User input to edit form
$('#edit_employee_page').on('click' , function () {
var editEmployee = JSON.stringify({
id: employees.length+1,
employeeno: $('#employeeno').val(),
employeename:$('#employeename').val(),
stateoforigine:$('#stateoforigine').val(),
employeephone: $('#employeephone').val(),
dateofbirth:$('#dateofbirth').val()
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
for (var i in employees) {
var id = JSON.parse(localStorage.getItem(employees[i]));
}
Here is my code for the Edit button:
//register Edit button
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
e.stopPropagation();
$.each(employees, function(a, b) {
//if(b.id == employees[i]){
$('#id').val(b.id);
$('#employeeno').val(b.employeeno);
$('#employeename').val(b.employeename);
$("#stateoforigine").val(i.stateoforigine);
$('#employeephone').val(b.employeephone);
$('#dateofbirth').val(b.dateofbirth);
$("#id").attr("readonly","readonly");
$('#employeeno').focus();
$.mobile.changePage('#edit_employee_page');
return false;
//}
});
});
Here is my local Storage:
[
{"id":1,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1965"},
{"id":2,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":3,
"employeeno":"DEF/234/20014",
"employeename":"Bill Gates",
"stateoforigine":"Osun",
"employeephone":"080765432",
"dateofbirth":"12/11/1966"},
{"id":4,
"employeeno":"DAST/003/2003",
"employeename":"Gold Base",
"stateoforigine":"",
"employeephone":"",
"dateofbirth":"12/03/1986"}
]
Thanks for helping me out
The way you are storing your employees into localStorage is correct, but the way you are getting them out is incorrect. You stored your employees by stating:
localStorage.setItem("employees", JSON.stringify(employees));
So, in order to retrieve them, you must use:
var employees = JSON.parse(localStorage.getItem("employees"));
You see, you stored the data as a string with a key of "employees"; therefore, you can only retrieve it by that key. Since all data stored in localStorage is saved as a string, you must use JSON.parse() to convert the data back into an object - an array in this case. Then you can iterate over your employees.
Update:
You should be running this code as soon as the page is rendered (see below). I'm not sure how you're doing that - if you're using an IIFE or jQuery's document.ready() function. I don't think it's necessary to store an empty array into localStorage if none were loaded initially, so, I took your else clause out.
var employees = [];
if (localStorage.getItem('employees') !== null) {
employees = JSON.parse(localStorage.getItem('employees'));
}
Debug this line-by-line when it runs and make positive your employees variable contains data. If it doesn't contain data, well then, there's nothing to edit.
If, however, there is data, then execute your showEmployees() function. Oddly, I'm not seeing in your code where you actually call this. Is it bound to a button or action in your UI? Also, what is that for loop doing after your $('#edit_employee_page') click event function? It's trying to read data from localStorage improperly and it does nothing.
I think if you simply stepped through your code one line at a time using breakpoints and desk-checking your inputs/outputs you'd find out where you're going wrong.
It also appears that there's a disconnect in your code. May be you left out some lines; you define a string editEmployee but out of the blues you store JSON.stringify(employees) whereas employees is not defined in your code:
$('#edit_employee_page').on('click' , function(){
var editEmployee = JSON.stringify({
id: employees.length+1,
//........
});
//Alter the slected data
localStorage.setItem("employees", JSON.stringify(employees));
return true;
});
I had a similar task to do . I did it this way.
I passed the dynamic Id to be passed as an id attribute
id="'+empData.id+'"
and then inside the
$('.edit_button').live('click', function (e) {
alert('I was Cliked!');
var empId=$(this).attr('id');
rest of the code is same.
I have tried many various ways to insert data (see the // comments). But still it doesn't seem to insert the data in either chromium or firefox (with ubuntu).
Full example:
`
<!doctype html>
<html><head>
<meta charset="UTF-8">
<script type = "text/javascript" src="jquery-1.11.0.js"></script>
<script type = "text/javascript" src="jquery.indexeddb.js"></script>
</head><body><script type = "text/javascript">
var key = null;
// Simply open the database once so that it is created with the required tables
$.indexedDB("BibleWay", {
"schema": {
"1": function(versionTransaction){
var catalog = versionTransaction.createObjectStore("context", {
keyPath: 'keyPath', autoIncrement: true
});
catalog.createIndex("bid");
catalog.createIndex("bk");
catalog.createIndex("c");
catalog.createIndex("v");
catalog.createIndex("t");
},
}
}).done(function(){
// Once the DB is opened with the object stores set up, show data from all tables
window.setTimeout(function(){
downloadCatalog();
}, 200);
});
function downloadCatalog(){
$.getJSON("3.json", function(data){
$.indexedDB("BibleWay").transaction("context").then(function(){
console.log("Transaction completed, all data inserted");
// loadFromDB("catalog");
}, function(err, e){
console.log("Transaction NOT completed", err, e);
}, function(transaction){
var catalog = transaction.objectStore("context"),$doadd,i2=0;;
catalog.clear();
/*$.each(data, function(i){
_(catalog.add(this));
})*/
$.each(data, function( index, value ) {
// bible id [bid]
var split_bid=index;
$.each(value, function( index, value ) {
// bible book name
var split_bk=index;
$.each(value, function( index, value ) {
// bible book chapter
var split_c=index;
$.each(value, function( index, value ) {
//var $doadd={"bid":split_bid,"bk":split_bk,"c"=split_c ,"v"=index,"t"=value};
//$doadd="{bid:\""+split_bid + "\",bk:\"" + split_bk + "\",c=" + split_c + ",v=" + index + ",t=\"" + value+"\"}";
$doadd=new Object();
$doadd.bid=split_bid;
$doadd.bk=split_bk;
$doadd.c=split_c;
$doadd.v=index;
$doadd.t=value;
catalog.add($doadd);
if (i2<10) {
console.log($doadd);
++i2;
}
//catalog.add(JSON.stringify($doadd));
//catalog.add({bid:split_bid,bk:split_bk,c:split_c,v:index,t:value});
//console.log(split_bid + " " + split_bk + " " + split_c + " " + index + ": " + value );
})
})
})
});
})
}
);
}
//$.indexedDB("BibleWay").deleteDatabase();
</script></body></html>
`
The JSON file "3.json":
{"3":{"GEN":{"1":{"1":"In the begynnynge God created heaven and erth."}}}}
Console Messages:
XHR finished loading: "http://host.host/3.json". jquery-1.11.0.js:9666
Object {bid: "3", bk: "GEN", c: "1", v: "1", t: "In the begynnynge God created heaven and erth."}
Transaction completed, all data inserted.
I found a bug in the jquery indexeddb api first that i fixed by commenting the line 90:
//e.name = "exception";
dfd.rejectWith(idbRequest, ["exception", e]);
This test is based on the code found in this example: http://nparashuram.com/jquery-indexeddb/example/
Thank you for your help
It's important and common for a library to surface any underlying errors, so if you've got some error messages or other warnings please update your answer to include them. I am wondering in particular whether your transaction has autocommited before the write was attempted.
I'm not too familiar with this API, but I see a common antipattern in that you are chaining your store creation and data insertion. Unless your jQuery library has designed around this common pattern, you could be running into that trouble here.
In IDB all action happens in a transaction. When you create modify anything related to a store or index you need what in IDB parlance is called a versionchange event. While such a transaction is capable of writing, reading and modifying schema, a phenomena us developers notice is that it ends up "autocommiting" despite your best attempts to keep it alive using closures, which maintain a reference to the commit and thereby should (I believe) keep it from commiting.
In case that's the problem, I suggest you decompose your callback hell into smaller helldoms: one for the object store, one for the object insertion. What this tends to do is create two closures around your versionchange and readwrite transactions and makes sure each operation completes successfully.