How can I do ng-repeat with a firebase Array? - javascript

Context
In a Firebase DB I'm storing "events" and "users". Users can have favorite events, to manage them I only store the event's id in the favorite user's DB location. So to grab favorite events informations, I need to firstable grab the event id and then go to the DB events location, to collect all the datas I need.
Problem
I would like to store in an Array all the favorite events informations (each event would be an Object with inside it : "key" : "value"), to use that Array in my HTML view and print the informations. But it doesn't work the way I coded it... :(
// This ref is too grab favorite event id (in my case only 2) in the user DB location
var refUserFavoris = firebase.database().ref().child("users/"+user.uid+"/events/favoris");
$scope.favorisTmp = $firebaseArray(refUserFavoris);
// This shows one array, with two objects (wich are my two user's favorite events) wich include ids
console.log($scope.favorisTmp);
// This is to load the objects and with the foreEach, grab there ids to use them in the next ref call
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
// This shows two lines : the id of each object
console.log(favoris.$id);
// Call a new ref to reach the event informations (in a different location of the DB) using the previous id
firebase.database().ref("events/"+favoris.$id).once('value').then(function(snapshot)
{
// Attempt to store events datas for each id I have (in my case, only two)
snapshot.forEach(function(favorisSnap)
{
var favSnap = favorisSnap.val();
// This shows a lot of "undefined" lines, wich I don't want. I would like two objects, with all informations inside
console.log(favSnap.nbPersonne);
// $scope.favorisF is an Array that I would like to use in a ng-repeat to print all datas for each event
// For now this doesn't show anything
$scope.favorisF = favSnap;
});
// If using favSnap out of the previous function, I got a "favSnap" is undifined error
console.log(favSnap);
});
});
});
<ion-item ng-repeat="f in favorisF" class="item-avatar">
{{f.nbPersonne}}
</ion-item>
EDIT 1 :
I tried a new way to have my data, but a new problem came, how to fill an Array inside a loop ? I've tried "push" and "$add" methods, but no one worked. Any ideas ?
var newFav = [];
var user;
user = firebase.auth().currentUser;
var refUserFavoris = firebase.database().ref().child("users/"+user.uid+"/events/favoris");
$scope.favorisTmp = $firebaseArray(refUserFavoris);
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
console.log(favoris.$id);
var refFavoris = firebase.database().ref("events/"+favoris.$id);
refFavoris.on('value', function(snap)
{
//This is where I'm trying to fill "newFav" in each steps of the loop
newFav.push(snap.val());
console.log("Scope newFav vaut :", $scope.newFav);
});
});
});

I think you made a typo here.
var refUserFavoris = firebase.database().ref("events/favoris/"+favoris.$id).once('value')

Thanks a lot Abdel, I fixed my problem :
Here is the solution
$scope.newFav = [];
console.log($scope.newFav);
$scope.favorisTmp.$loaded().then(function()
{
angular.forEach($scope.favorisTmp, function(favoris)
{
console.log(favoris.$id);
var refFavoris = firebase.database().ref("events/"+favoris.$id);
refFavoris.on('value', function(snap)
{
$scope.newFav.push(snap.val());
console.log("Scope newFav vaut :", $scope.newFav);
});
});
});

Related

javascript - JSON file use a value only if key exists

I'm retrieving an OSM Json from an overpass call, to obtain a list of features that I have to save on a database. Since the data are very different from one another (for example, some of them do have a a tag called "addr:city", and some of them not), I would like to check if a key exists, and only in that case save the corresponding value. I've found only this question but it's not my case, since I do not know a priori which keys one element will have and which not, and since I'm working with a great load of data, I really can't check the elements one by one and of course I can't write an IF for each case.
Is there a way to solve this? I was thinking something about "if key has null value, ignore it", while looping over the elements, but I don't know if something like that exists
EDIT:
This is my query:
https://overpass-api.de/api/interpreter?data=[out:json][timeout:25];(node[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696);way[~%22^(tourism|historic)$%22~%22.%22](44.12419,%2012.21259,%2044.15727,%2012.27696););out%20center;
and this is the code I'm using to save the data on firebase:
results.elements.forEach(e=>{
var ref = firebase.database().ref('/point_of_interest/');
var key = firebase.database().ref().child('point_of_interest').push().key;
var updates = {};
var data = {
città: e.tags["addr:city"],
tipologia: e.tags["amenity"],
indirizzo: e.tags["addr:street"],
nome: e.tags["name"],
lat: e.lat,
lon: e.lon
}
updates['/point_of_interest/'+key] = data;
firebase.database().ref().update(updates);
})
"results" is the response in json format
You could use something like that:
var attrs = ["addr:city", "amenity", "addr:street", "name"];
var labels = ["città", "tipologia", "indirizzo", "nome"]
var data = { };
attrs.forEach((a, i) => {
if (e.tags[a]) { data[labels[i]] = e.tags[a]; }
});
You could even make this more dynamic, if you can query the attribute names and labels from somewhere.

Delete a field from Firestore, with a dynamic key

I am trying to delete a single field from a Document in Firestore
The Key of the field is held in a variable e.g.
var userId = "random-id-1"
In the document I have a field of members structured like this:
{
members:{
random-id-1:true,
random-id-2:true
}
}
I would like to delete random-id-1:true, but keep random-id-2:true
How is this possible without getting the entire members object and writing an updated object?
I have tried this, however I get the error: Document references must have an even number of segments
and I also tried this:
db.collection('groups').doc(this.props.groupId).set({
members: {
[userId]: firebase.firestore.FieldValue.delete()
}
},{merge: true})
However I get the error: Function DocumentReference.update() called with invalid data. FieldValue.delete() can only appear at the top level of your update data
Thanks for any help
I have managed to delete a field like this:
let userId = "this-is-my-user-id"
let groupId = "this-is-my-group-id"
db.collection('groups').doc(groupId).update({
['members.' + userId]: firebase.firestore.FieldValue.delete()
})
This is using the dot operator method described here
Please let me know if there are any alternative methods to this
Thanks
I had to import FieldValue
https://firebase.google.com/docs/firestore/manage-data/delete-data#fields
// Get the `FieldValue` object
var FieldValue = require('firebase-admin').firestore.FieldValue;
// Create a document reference
var cityRef = db.collection('cities').doc('BJ');
// Remove the 'capital' field from the document
var removeCapital = cityRef.update({
capital: FieldValue.delete()
});

Firebase Web get first Child data from autoChildID

My database looks like this:
I am trying to get the first child of unassignedBeaconIDs, read the data beaconID, major, minor and delete it from unassignedBeaconIDs.
Here is my code:
var refBeaconID = firebase.database().ref(pathToBeaconIDs).limitToFirst(1);
refBeaconID.once('value', function(snap)
{
var firstItem = snap.val(); // first item, in format {"<KEY>": "<VALUE>"}
console.log("The first item");
console.log(firstItem.beaconID);
refBeaconID.child(firstItem.key).removeValue;
});
The problem is the childAutoID Value. I always get undefined as a result.
When you execute a query against the Firebase Database, there will potentially be multiple results. So the snapshot contains a list of those results. Even if there is only a single result, the snapshot will contain a list of one result.
So you'll need to loop over the children of the snapshot in your callback:
var refBeaconID = firebase.database().ref(pathToBeaconIDs).limitToFirst(1);
refBeaconID.once('value', function(snap)
{
snap.forEach(function(child) {
var firstItem = child.val();
console.log("The first item");
console.log(firstItem.beaconID);
});
});
I'm not completely certain what refBeaconID.child(firstItem.key).removeValue; translated to, but if you want to delete the child after logging it: child.ref.remove();.

Prevent a duplicate item being added in Localstorage with AngularJS

I am working on a prototype that stores products (like a favourite) into localStorage but I am struggling to check to see if an item already exists in localStorage so its not added again.
Where would the best place be to check for a duplicate entry and handle it gracefully?
My sample controller is below:
function dCtrl($scope, $filter) {
$scope.d = [
{id:'1',d_name:'Product 1',colour:'Blue'},
{id:'2',d_name:'Product 2',colour:'Red'},
{id:'3',d_name:'Product 3',colour:'Cream'},
{id:'4',d_name:'Product 4',colour:'White'},
{id:'5',d_name:'Product 5',colour:'Green'},
{id:'6',d_name:'Product 6',colour:'Black'},
{id:'7',d_name:'Product 7',colour:'Purple'},
{id:'8',d_name:'Product 8',colour:'Grey'},
{id:'9',d_name:'Product 9',colour:'Yellow'},
{id:'10',d_name:'Product 10',colour:'Indigo'}
];
$scope.getDetails = function (id, favDresses) {
//get the object of the item clicked
single_object = $filter('filter')($scope.d, {id:id})[0];
// If you want to see the result, check console.log
console.log(single_object);
console.log('ID:' + id + ' - save this object to localStorage');
//set localstorage var
var storage = localStorage.getItem('newfavdresses');
//check to see if the localStorage array is empty (not null)
if(storage != null) {
//if it isnt, parse the string
favDresses = JSON.parse(localStorage.getItem('newfavdresses'));
//push into the array
favDresses.push(single_object);
//set the item in localstorage
localStorage.setItem("newfavdresses",JSON.stringify(favDresses));
} else {
//if the array is null, create it
var favDresses = [];
//and push the item into it
favDresses.push(single_object);
//set the item in local storage
localStorage.setItem("newfavdresses",JSON.stringify(favDresses));
}
}
$scope.clearStorage = function() {
localStorage.clear();
alert('Local Storage Cleared');
}
//get localStorage items
var dresses = localStorage.getItem("newfavdresses");
dresses = JSON.parse(dresses);
console.log(dresses);
}
jsFiddle demo - https://jsfiddle.net/dwhiteside86/Lt7aP/2261/
My suggestion is work with live javascript array stored in service.
You would load this array from localStorage when service initializes or set to empty array if nothing in storage.
Then whenever you update the stored array you always store back the whole thing into localStorage so that the stored version is always a string replica of the live one.
This way you only use getItem() once and then have a simple service method storeLocal() that you call each time you modify array or object in array.
Another thing you might look at is ngStorage that does all of the above for you
Look at https://github.com/grevory/angular-local-storage, I believe it will solve all your issues. This library will bind your scope property to local storage so You'll dont care about how it stores.

Alfresco: update data list line

I have data being sent to a custom data list from the following code:
// Get the site name and dataLists
var site = siteService.getSite("Testing");
var dataLists = site.getContainer("dataLists");
// Check for data list existence
if (!dataLists) {
var dataLists = site.createNode("dataLists", "cm:folder");
var dataListProps = new Array(1);
dataListProps["st:componentId"] = "dataLists";
dataLists.addAspect("st:siteContainer", dataListProps);
dataLists.save();
}
// Create new data list variable
var orpList = dataLists.childByNamePath("orplist1");
// If the data list hasn't been created yet, create it
if (!orpList) {
var orpList = dataLists.createNode("orplist1","dl:dataList");
// Tells Alfresco share which type of items to create
orpList.properties["dl:dataListItemType"] = "orpdl:orpList";
orpList.save();
var orpListProps = [];
orpListProps["cm:title"] = "Opportunity Registrations: In Progress";
orpListProps["cm:description"] = "Opportunity registrations that are out for review.";
orpList.addAspect("cm:titled", orpListProps);
}
// Create new item in the data list and populate it
var opportunity = orpList.createNode(execution.getVariable("orpWorkflow_nodeName"), "orpdl:orpList");
opportunity.properties["orpdl:nodeName"] = orpWorkflow_nodeName;
opportunity.properties["orpdl:dateSubmitted"] = Date().toString();
opportunity.properties["orpdl:submissionStatus"] = "Requires Revisions";
opportunity.save();
This correctly creates data list items, however, at other steps of the workflow require these items to be updated. I have thought of the following options:
Remove the data list item and add another with the updated information
Simply update the data list item
Unfortunately I have not found adequate solutions elsewhere to either of these options. I attempted to use orpWorkflow_nodeName, which is a unique identifier generated at another step, to identify a node to find it. This does not seem to work. I am also aware that nodes have unique identifiers generated by Alfresco itself, but documentation doesn't give adequate information on how to obtain and use this.
My question:
Instead of var opportunity = orpList.createNode(), what must I use in
place of createNode() to identify an existing node so I can update its
properties?
You can use this to check existing datalist item.
var opportunity = orpList .childByNamePath(execution.getVariable("orpWorkflow_nodeName"));
// If the data list Item is not been created yet, create it
if (!opportunity ) {
var orpList = orpList .createNode(execution.getVariable("orpWorkflow_nodeName"),"dl:dataList");}

Categories