I am working on real-time fire-base database.
i have a issue in getting value what is changed in fire-base.
i have client social database inside it posts and then kkkm(this is key) and then different properties and values and what i want is to toggle approval and rejected values like that approval:true but what i get is just true/false not the property name.
toggleCheck = (id) => {
var ref = firebase.database().ref('posts/'+id);
ref.off("child_changed");
var approval;
ref.on("child_changed", function (data) {
approval = data.val();
console.log("=============================");
console.log("The updated approval is " + approval);
});
}
toggleClose = (id) => {
var ref = firebase.database().ref('posts/'+id);
ref.off("child_changed");
var rejected;
ref.on("child_changed", function (data) {
rejected = data.val();
console.log(ref.getKey());
console.log(ref.getValue());
console.log("=============================");
console.log("The updated rejected is " + rejected);
});
}
I'm not 100% sure to understand what you want to do ("toggle approval and rejected values"?) but, based on the code in your question, the following is probably what you are looking for:
var ref = firebase.database().ref('posts/' + id);
ref.on('child_changed', function(data) {
console.log(data.key); // <-- Name of the field/node that was modified
console.log(data.val()); // <-- Value of the field/node that was modified
console.log("The updated" + data.key + " is " + data.val());
});
Explanations:
data is a DataSnapshot which has:
A key property, which is "the key (last part of the path) of the location of this DataSnapshot."
A val() method, which "extracts a JavaScript value from a DataSnapshot."
UPDATE FOLLOWING YOUR COMMENTS
I understand that you want to get both the values of the approval and rejected nodes (fields) when something changes in the post.
Therefore you should use the value event type instead of the child_changed one, as follows:
var ref = firebase.database().ref('posts/' + id);
ref.on('value', function(data) {
var approved = data.val().approved;
var rejected = data.val().rejected;
var object = {'approved': approved, 'rejected': rejected};
//Do whatever you want with the object
console.log(object);
});
Related
I am running into a peculiar problem.
I have a my view of drop down list as this in HTML:
<div ng-controller='ConfigurableInputController as configurableInput'>
<select class="fixed-input"
ng-model="configurableInput.selectedCriteria"
ng-change="configurableInput.update()"
ng-options="criterion.selected as criterion.name for criterion in configurableInput.criteriaList">
<option value="">--Please select the comparison criteria--</option>
</select>
The above shows me 3 options in drop down list: Store, Channel and Permissions.
When ever I change the option from Store to Channel or Permissions or any combination the view changes (input boxes, certain labels etc.)
My update() method in controller does this:
configurableInput.update = function () {
configurableInput.permission = "";
configurableInput.id1 = "";
configurableInput.id2 = "";
configurableInput.items1 = "";
configurableInput.items2 = "";
configurableInput.defaultValueArray = [];
configurableInput.permissionsArr = [];
}
On selection of the drop down item, I do a ng-click on a button which retrieves information from Db.
There are 2 flavors of methods which are called on ng-click but the one giving me trouble is this one in the Service method:
StoreConfigurableService.$inject = ['$q', '$http', 'ApiBasePath'];
function ConfigurableService($q, $http, ApiBasePath) {
var service = this;
var defaultValueArr = [];
var permissionsArr = [];
var items1 = "";
var items2 = "";
service.retrievePermissions = function (criterion, id1, id2, rlNumber1, rlNumber2) {
$q.all([
$http.get(ApiBasePath + "/" + criterion + "/" + id1 + "/" + rlNumber1),
$http.get(ApiBasePath + "/" + criterion + "/" + id2 + "/" + rlNumber2)
])
.then(function (response) {
items1 = response[0].data;
items2 = response[1].data;
if (criterion === 'Permissions') {
var processed = false;
permissionsArr = makePermissionsArray(permissionsArr, items1, items2, processed);
}
})
.catch(function (errorResponse) {
console.log("Error: " + errorResponse);
throw errorResponse;
});
};
... so on
In my makePermissionsArray() I am doing this:
function makePermissionsArray(arr, items1, items2, processed) {
var map = items1.storePermissions;
var map2 = items2.storePermissions;
var map3 = items1.allPermissions;
for (var key in map) {
arr.push({
'code': key,
'description': map3[key],
'repStorePermission1': map[key],
'repStorePermission2': map2[key]
});
}
}
I get this permissionsArr back to controller through this:
service.getPermissionsArr = function () {
return permissionsArr;
};
NOTE that 'arr' in the argument of method makePermissionsArray() is not initialized because I am getting it by passing permissionsArr in the argument.
Now how the flow goes is:
First I select Store from drop down list, click on button to retrieves configurables for the store. This gives me correct response.
Then I select 'Permissions' from drop down list, click on button to retrieve permission configurables from Db, it gets stuck and does not get me any response.
I thought I am not clearing the arrays correctly in update() method and after some long search I found and changed these array initializing from:
configurableInput.defaultValueArray = [];
configurableInput.permissionsArr = [];
to
configurableInput.defaultValueArray.length = 0;
configurableInput.permissionsArr.length = 0;
in my update() method.
Now what happens is this:
First I select Store from drop down list, click on button to retrieves configurables for the store. This gives me correct response.
Then I select 'Permissions' from drop down list, click on button to retrieves permission configurables from Db, it gives me correct response.
I select Store from drop down list again, click on button and I get correct response.
But when I again select 'Permissions' from drop down list, click on button, it gives me this error - TypeError: Cannot read property 'push' of undefined
Error I get is at this point:
arr.push({
'code': key,
'description': map3[key],
'repStorePermission1': map[key],
'repStorePermission2': map2[key]
});
I am literally tearing my hair out because of this problem. Can someone please help me what's wrong?
can anybody help me? I'm having a problem similar to the previous post. I'm just not getting the child object. I have tried in several ways the most basic and logical would be: newPost.musician.statusbatera
Follows a chrome debug print: --Screen Shot--
I'm not getting it because of the key generated automatically by firebase as the print in attached.
My code:
var db = firebase.database();
var ref = db.ref("users");
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
console.log("Musician: " + newPost.musician.statusbatera);
});
You can grab the autogenerated key using Object.keys, then you can assign the object you need:
ref.on("child_added", function(snapshot) {
var newPost = snapshot.val();
keys = Object.keys(newPost.musician)
console.log("Musician: " + newPost.musician[keys[0]].statusbatera);
});
in theory, there should be only one value in keys...
I think you want to iterate through musician's list, if so, give this a try :-
for(var i = 0; i <= newPost.musician.lenght; i++) {
console.log("Musician: " + newPost.musician[i].statusbatera);
}
I have this database
service/
-KSxobYDhjUJeSvu3dC1
-Accion:"Nueva ronda"
-Codigo: 3
-dateTime: 1475284727
-notify: 0
-num_mesa: 0
-KSxobptdYSc-qrCSbyU
-Accion: "Orden cancelada"
-dateTime: 1475284728
-notify: 0
-num_mesa: 0
and then I have this code:
ref.orderByChild("notify").equalTo(1).limitToLast(1).on("child_added", function(snapshot) {
var changedPost = snapshot.val();
var mykey = snapshot.key;
if(changedPost.notify == 1 ){
var message = "New action "
console.log(serviceArray[mykey].notify);//undefined
$scope.showActionToast(message);
}
});
This code will read the last entry in the database and show a toast, notifying that a new action has been inserted in firebase. It shows the toast.
My problem is that I don't want it to show every time i reload the page.
So I thought about adding a simple flag that if it was shown in a toast, it will change notify to 0.
My problem is that I have service that returns a firebaseArray named serviceArray. When I try to access the row to change the value it says undefined. How can I change the value in the same function?
You're going to be better off simply tracking the timestamp of the last message you've shown to the user. With that you can query for messages that were added after that timestamp:
var timestampOfMostRecentlySeenMessage = null;
if (timestampOfMostRecentlySeenMessage) {
ref.orderByChild("timestamp")
.startAt(timestampOfMostRecentlySeenMessage)
.limitToLast(1)
.on("child_added", function(snapshot) {
var message = snapshot.val();
timestampOfMostRecentlySeenMessage = message.dateTime;
})
Now you just need to maintain the value of timestampOfMostRecentlySeenMessage between page reloads. You could do this in a cookie, in local storage of your browser or even in a user-specific part of your database:
var userRef = firebase.database().ref("users").child(user.uid);
userRef.child("timestampOfMostRecentlySeenMessage").set(timestampOfMostRecentlySeenMessage);
i just added a flag that declares after running the search for the first time.
ref.orderByChild("notify").equalTo(1).limitToLast(1).on("child_added", function(snapshot) {
var changedPost = snapshot.val();
var mykey = snapshot.key;
if(changedPost.notify == 1 && $scope.flag== 1 ){
var message = "New action "
console.log(serviceArray[mykey].notify);//undefined
$scope.showActionToast(message);
}
$scope.flag= 1;
});
I'm using angularfire 1.1.1 to store my apps objects and each object creates associated indexes. So when a user is created, that user is added to the 'users' table and then the users index table gets keyed with the UID and points to the actual user's id.
When the main state is called, I run a checkAuth() method to see if a user is signed in. If so, then I want to assign $rootScope.auth = {id:userID, role: role} etc.
The function works great in my login method but i don't know how to grab the value from my checkAuth() method. I've tried $value on both $firebaseObject and $firebaseArray, also tried to call them with [0] since there is only one id value in the table for each user's uid.
The sloppy regex is for changing the semi-colon from SimpleLogin:47 to SimpleLogin-47 for keying to the index.
Here's the code that doesn't work:
function authCheck(){
var getAuth = $firebaseAuth(Data.ref);
console.log('signed in as', getAuth.$getAuth().uid);
var uid = getAuth.$getAuth().uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
var userIndexRef = Data.ref.child('index/users/uid/'+uid);
var userIndexArray = $firebaseArray(userIndexRef);
var userIndexObject = $firebaseObject(userIndexRef);
console.log(userIndexArray, userIndexObject);
var realId = '';
angular.forEach(userIndexObject, function(key, id){
realId = id;
$rootScope.auth = realId;
return realId;
});
}
Here's the login code that does work:
function login(email, pass) {
ref.authWithPassword({email:email,password:pass}, function(error, authData){
if (error) {
console.log(error);
} else {
console.log('signed in as',authData.uid);
var uid = authData.uid.toLowerCase().replace(/'+/g, '').replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "-").replace(/^-+|-+$/g, '');
angular.forEach(Data.dataObject.index.users.uid[uid],function(id, key){
$rootScope.role = Data.dataObject.users[id].role;
$rootScope.auth = {authData:authData, id:id, role:Data.dataObject.users[id].role};
});
}
});
}
If anyone sees where I've messed up, I'll be happy to know. Here's the repo https://github.com/irthos/medviz if it helps. Thank you very much!
This problem has me stumped.
For some reason, the autoincrementing key generator in indexedDB resets after performing and update on an existing object with a put-transaction, leading to overwrites of data in the database.
For my app, I'm using a self written IndexedDB service for angularJS with all the basic CRUD functions implemented.
I may also add that I'm developing with Ionic Framework, even though I doubt that is to blame.
Considering the service is a work-in-progress, I've let the key path for an object store default to "id" with an autoincrementing strategy.
The indices for the given store, nevertheless, are up to the user to decide in a specific object.
As an example:
dbHelper.objectStores = [{'employees',
indices: [{indexName: 'name', isUnique: false},
{indexName: 'phone', isUnique: true}]}];
This would, unless already created in the db, create the object store 'employees' with indices 'name' and 'phone', where 'phone' would have to be a unique value while 'name' would not.
Here is the implementation of the openDB function.
Please note that dbHelper.objectStores is supposed to be empty as it's up to the user to assign these properties before opening the db(or else it is defaulted).
angular.module('dbProvider', [])
.factory('$db', ['$window', function($window) {
// DB Object
var dbHelper = {};
// Properties - Are given defaults unless assigned manually by user before openDB is invoked.
dbHelper.dbName = 'defaultDB';
dbHelper.dbVersion = 1;
dbHelper.objectStores = [];
dbHelper.openDB = function(onCompleteCallback, onErrorCallback) {
console.log('Atempting to open db with name ' + dbHelper.dbName + '.');
var request = $window.indexedDB.open(dbHelper.dbName, dbHelper.dbVersion);
// Invoked by indexedDB if version changes
request.onupgradeneeded = function(e) {
console.log('Version change. Current version: ' + dbHelper.dbVersion);
var db = e.target.result;
e.target.transaction.onerror = onErrorCallback;
if(dbHelper.objectStores.length === 0) {
dbHelper.objectStores.push({name:'defaultStore', indices: []});
}
for(var store in dbHelper.objectStores) {
if(db.objectStoreNames.contains(dbHelper.objectStores[store].name)) {
console.log(dbHelper.objectStores[store].name + ' deleted.');
db.deleteObjectStore(dbHelper.objectStores[store].name);
}
var newStore = db.createObjectStore(dbHelper.objectStores[store].name, {keyPath: "id", autoIncrement: true});
for(var index in dbHelper.objectStores[store].indices) {
newStore.createIndex(dbHelper.objectStores[store].indices[index].indexName,
dbHelper.objectStores[store].indices[index].indexName,
{unique : dbHelper.objectStores[store].indices[index].isUnique});
}
console.log(dbHelper.objectStores[store].name + ' created.');
}
};
request.onsuccess = function(e) {
console.log('DB ' + dbHelper.dbName + ' open.');
dbHelper.indexedDB.db = e.target.result;
onCompleteCallback();
};
request.onerror = onErrorCallback;
};
Here are some of the CRUD functions(the ones in question):
dbHelper.findItemWithIndex = function(keyValue, storename,
onCompleteCallback,onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var index = store.index(keyValue.key);
index.get(keyValue.value).onsuccess = function(event) {
onCompleteCallback(event.target.result);
};
};
dbHelper.addItemToStore = function(item, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.add(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.deleteItemFromStore = function(itemId, storename,
onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.delete(itemId);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
dbHelper.updateItem = function(item, storename, onCompleteCallback, onErrorCallback) {
var db = dbHelper.indexedDB.db;
var trans = db.transaction([storename], "readwrite");
var store = trans.objectStore(storename);
var request = store.put(item);
trans.oncomplete = onCompleteCallback;
request.onerror = onErrorCallback;
};
Finally, the code from the controller where the transactions are invoked.
The strategy here, is that the item is added to the db using the addItemToStore function the first time it is persisted, and then afterwards the updateItem function.
After adding the first time, the object is immediately fetched in order to keep working on it with the assigned id from the db.
$scope.updateTemplate = function() {
console.log('Saving..');
var onCompleteCallback = {};
if(!$scope.formTemplate.firstSave) {
onCompleteCallback = $scope.updateModel;
} else {
$scope.formTemplate.firstSave = false;
onCompleteCallback = $scope.setId;
}
$db.updateItem($scope.formTemplate, $scope.objectStore.name,
onCompleteCallback, $scope.dbError);
};
$scope.newItem = function() {
$db.addItemToStore($scope.formTemplate, $scope.objectStore.name,
$scope.setId, $scope.dbError);
};
$scope.setId = function() {
$db.findItemWithIndex(
{key: 'title',
value: $scope.formTemplate.title},
$scope.objectStore.name,
function(result) {
console.log(JSON.stringify(result));
$scope.formTemplate = result;
},
function(error) {
$scope.dbError(error);
});
}
It's here everything goes to hell.
I add an object, go back to another view and find it in the list with id=1.
I add another object, go back to the list view, and there it is with id=2.
And so forth and so forth..
Then, after updating either of the objects with the $scope.updateTemplate function, which also works like a charm, things get interesting:
The next object added gets id=1 and totally erases good old numero uno from earlier.
The next objects also get id's that cause them to replace the already existing objects.
What could cause this?
For testing I'm using Safari 8 in OS 10.10 and I'm deploying to an LGG2 with KitKat 4.4.2.
To be honest, I skimmed, but I saw this, "Safari 8" - the latest iOS and Safari have serious bugs with IndexedDB: http://www.raymondcamden.com/2014/9/25/IndexedDB-on-iOS-8--Broken-Bad
In iOS9, many of the IndexedDb bugs are fixed, but not all. We are currently testing on iOS9 Beta 2 and this particular bug that you found is not fixed.
We were able to work around this problem by not using autoincrement on our object stores. We just manually find the max key value and increment that.
Inserting an object looks something like this:
var store = db.transaction([entity], "readwrite").objectStore(entity);
store.openCursor(null, "prev").onsuccess = function (event) {
var maxKey = event.target.result.key || 0;
object.id = maxKey + 1;
store.add(object);
}