How to remove any firebase data using JavaScript? - javascript

I am building a web application using JavaScript and firebase.
everytime I click on the "remove" paragraph tag, I can only remove the most recent added item, but cannot remove the rest.
Example: if I have 9 items, and I just added a 10th item, I can only remove the 10th item, but not the other 9 items. I basically can only remove items in a backwards order, as opposed to being able to remove items in any order of my choice.
Here is my code:
function displayFav(){
const dbRef = firebase.database().ref();
dbRef.on("value", (firebaseData) => {
// empty out element before adding new updated firebase data so there are no repeated data
document.getElementById("displayUsername").innerHTML = "";
let accounts = [];
const accountData = firebaseData.val();
for (let itemKey in accountData) {
accountData[itemKey].key = itemKey;
accounts.push(accountData[itemKey])
const key = accountData[itemKey]["key"];
const password = accountData[itemKey]["password"];
let user = accountData[itemKey]["username"];
// code where I try to render results from page
document.getElementById('displayUsername').innerHTML += `
<li> Username: ${user} Password: ${password}</li>
<p id=${key}>Remove</p>
`;
// code where I try to remove the item
document.getElementById(key).addEventListener("click", function(){
removeItem(key)
})
}
});
}
This is my function to remove the firebase data:
function removeItem(itemToRemove){
const dbRef = firebase.database().ref(`${itemToRemove}`);
dbRef.remove();
};
What can I change or add to my code that will allow me to remove items in any order I want, instead of letting me delete only the most recent items?

Not trying to be rude, this is just a tip: Please indent/format your code well so that people can understand it without having to format it themselves. Usually when people see large code that's not well formatted, it throws them off (sometimes including me), and therefore they wouldn't want to continue to read or help you with the question.
Suppose you have a table called posts, and the structure looks like this:
that is:
{
<postId>: {
date: 1518925839059,
message: 'some message'
},
<postId>: {
date: 151892583967,
message: 'some message'
},
...
...
}
Suppose you want to delete the extra property of the first post, as circled in the picture, you must know the full path of the data:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8/extra').remove();
If you want to delete everything in post 1:
firebase.database().ref('posts/-L5b1EZ1L_FycluzTIn8').remove();
Or, if you want to delete every single post:
firebase.database().ref('posts').remove();

Related

Js/React : Find ONLY the elements whitin an array that matches X condition to get X results

Im getting different elements from an array that comes from the backend like so :
data = [{id: '1', collection: 32, isNew: true},{id: '5', collection: 22, isNew: false}, .... ]
The user is allowed to select in a massive way differents Ids, and edit them, and I need to show a different modal for each different cases :
The conditions to show the differents modals are based on : If I select only the ones that has isNew = true, if I select only the ones with isNew= false, or if I select both Id cases isNew=false and isNew=true.
So far Ive tried this :
const getNewInfo = data.some(item => item.isNew)
if(getNewInfo) {
return this.explainNewInfo(true)
} else if(!getNewInfo) {
return this.explainNewInfo(false)
} else {
return this.explainNewInfo()
}
I also tried with the filter method and push to a new array, but it relies on the same logic at the end. For the first both cases, it works fine, but in the 3rd case, I cant get in, since whenever matches that isNew is true, it gets in there, and discard all the rest of posibilites.
Each function that is being called on the if else, is a function that recives or not a parameter indicating if is necessary to show a certain modal for the 3 differentes cases.
You can use every function on an array to check for all objects. Read about every.
const isAllNewInfo = data.every(item => item.isNew)
const isAllOldInfo = data.every(item => !item.isNew)
if (isAllNewInfo) {
return this.explainNewInfo(true)
} else if(isAllOldInfo) {
return this.explainNewInfo(false)
} else {
return this.explainNewInfo()
}

unable to remove an object from localStorage using its id

function removeLocalStorageHelper(item, pizzaId) {
console.log(item.productID);
console.log(pizzaId);
if (item.productID == pizzaId) {
console.log("Working fine");
localStorage.removeItem(item);
console.log(localStorage);
}
}
function removeFromLocalStorage(pizzaId) {
var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
var cartRowContents = locStore.map((item) =>
removeLocalStorageHelper(item, pizzaId)
);
}
Whenever the user clicks on "Remove" button, removeFromLocalStorage() function is called which receives a number type variable pizzaId. Now, this pizzaId is stored in the localStorage and I want to remove the object associated with this pizzaId from my localStorage.
CONSOLE OUTPUT
Please help me to remove an object from localStorage using productID.
You can't directly remove an item from the stored array. For that you need to remove the intended element from array and insert again to localStorage like below. Otherwise it'll remove complete list from localStorage.
Note: You need to do the same wile adding new item to the localStorage.
function removeFromLocalStorage(pizzaId) {
var locStore = JSON.parse(localStorage.getItem("selectedProduct"));
var cartRowContents = locStore.filter((item) => item.productID !== pizzaId);
localStorage.setItem("selectedProduct", JSON.stringify(cartRowContents))
}
As I reivew your code, I see that you are retrieving the item from localStorage like this localStorage.getItem("selectedProduct") The question here is do you want to remove the entire locStore or just a part of it. Maybe locStore is a complex collection (array) from multiple products and not a single entity as this code hints
var cartRowContents = locStore.map((item) =>
removeLocalStorageHelper(item, pizzaId));
If this is the case you need to do something like this
var locStore = locStore.filter(function(item, index){
return item.productID != pizzaId;
});
Now you have a locStore collection without the item you want to remove and you have to save it back to localStorage like this
localStorage.setItem('selectedProduct', JSON.stringify(locStore));
Essentially you are overriding the old selectedProduct value in localStorage with a new one that does not contain the removed product.
If for some reason locStore is just a simple JSON object that you want to remove you can do this to delete it from localStorage
localStorage.removeItem('selectedProduct')
Well, if you just need to remove the selectedProduct, you can do it like this:
localStorage.removeItem("selectedProduct");

Using Button Click to Update Values Returned from Firestore in For Loop

I currently have a basic CRUD site that I started working on recently to list a number of products and the associated prices. My skills aren't the best but I am fighting the good fight and would like some assistance/guidance with what I am trying to achieve.
I have data stored in a Firestore database and I have it being pulled and shown in a list. In order to display it I have the values in my sub-collection being added to an array and then I am using a for loop to loop through and pull each value and display it using an html template string. I decided that since I have the create and display aspect of this to a decent point, I would like to add a button (or in my case an icon) that would allow me edit each value that is returned.
const shelf = doc.data();
doc.ref.collection("products").get().then((Snapshot) => {
const products = Snapshot.docs.map(doc => doc.data());
// start of for loop
for(let product of products){
// start of template string inside backticks
const li = `
<p><div>${product.name} <div class="right"><font class=pink-text>Price:</font> $${product.price} <i class="material-icons">create</i></div></div></p>
`;
// end of template string inside backticks
html += li;
// start of edit price section
let price = product.price;
const priceeditForm = document.querySelector('#priceedit-form');
priceeditForm.addEventListener('submit', (e) => {
e.preventDefault();
console.log("Document with ID: ", doc.id);
doc.ref.collection("vendors").doc(price)get().then((Snapshot) => {
const priceedit = Snapshot.docs.map(doc => doc.data());
price: priceeditForm['price'].value
}).then(() => {
// close the signup modal & reset form
const modal = document.querySelector('#modal-priceedit');
M.Modal.getInstance(modal).close();
priceeditForm.reset();
}).catch(err => {
console.log(err.message);
});
});
//end of edit price section
}
// end of for loop
productList.innerHTML = html;
});
I would like that when the icon is clicked, that a model pops up with a single input fields for the price and I can enter the new price and submit it, hence updating the value in the database.
I will be very grateful to anyone who can assist me with this. Thank you in advance.
Output Image
Thanks to everyone who assisted on this. I decided to redo my code from scratch using DOM elements to appendChild. Once done this made everything sooooo much easier. Decided to change it to give myself more flexibility with the code.

Implementing Infinite Scrolling with Firebase?

var self = this;
var firebaseRef = new Firebase(baseUrl + '/sparks');
firebaseRef.limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
self.addChild(childSnapshot); // adds post to a <div>
});
My code currently loads the last 5 posts and will load any new posts. However, I'd also like to be able to load older posts as well. I have a button that when clicked will call a function (that I'm unsure of how to implement) that loads older posts. How do I retrieve these older posts?
(The arrow just signifies that I want to retrieve posts starting from the bottom and working my way up to the top)
You need to think a bit backwards to do this. When you get the results for your query for the first page, remember the first item in the results:
firebaseRef.endAt().limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
self.addChild(childSnapshot); // adds post to a <div>
});
While you cannot access child items by index with Firebase, you can store the key of an item and use that to start a next query.
var firstKnownKey;
firebaseRef.orderByKey().limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
if (!firstKnownKey) {
firstKnownKey = childSnapshot.key;
}
self.addChild(childSnapshot); // adds post to a <div>
});
Now you have a variable firstKnownKey that has the first key you've ever seen. To get the previous batch of children, you pass that value in to endAt() when you fire your next query:
firebaseRef.orderByKey().endAt(firstKnownKey).limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
if (!firstKnownKey) {
firstKnownKey = childSnapshot.key;
}
self.addChild(childSnapshot); // adds post to a <div>
});
Answers to similar questions of the past few days:
Can I get the nth item of a firebase "query"?
Firebase results range using startAt and endAt
Since endAt() is inclusive, the last item gets repeated every time I do the infinite scroll, so I did a little modification to frank van puffen 's answer.
I initiate a list childrenVal to store all the values, another list childrenKey to store all the keys and a var firstKnownKey, as frank van puffen sugests.
var childrenVal=[];
var childrenKey=[];
var firstKnownKey = "";
For the first time you make the query, you get the last 5 elements:
getFirst(){
firebaseRef.orderByKey().limitToLast(5).once('value')
.then((snap)=>{
snap.forEach(childSnap => {
childrenVal.unshift(childSnap.val());
childrenKey.unshift(childSnap.key);
});
firstKnownKey = childrenKey[childrenKey.length-1];
});
}
In your next query, you won't want your firstKnownKey to get repeated, so I did the following function:
exclude(key){
return key.substring(0, key.length - 1) + String.fromCharCode(key.charCodeAt(key.length - 1) - 1)
}
and for the query itself, the following function:
getNext() {
firebaseRef.orderByKey().endAt(exclude(firstKnownKey)).limitToLast(5).once('value')
.then((snap) => {
snap.forEach(childSnap => {
childrenVal.unshift(childSnap.val());
childrenKey.unshift(childSnap.key);
});
firstKnownKey = childrenKey[childrenKey.length - 1];
});
}

Check if object value inside array, already exists in a different array of objects?

Plunker - http://plnkr.co/edit/jXdwOQR2YLnIWv8j02Yp
I'm using angular to build a view which has a list of users in the main container (array-A) and a sidebar of users which host any 'selected' users (array-B).
The first one (A) has all the users.
[{ $$hashKey: "00F", id: "118207f5e52c3eb619a8760bc08c8224", username: "John Smith" },
{ $$hashKey: "00G", id: "9c2d6f31c88e7a654e64bd0d3371360a", username: "Fredy Rincon" },
{ ... }]
The second one (B) has the users that are already selected (Firebase db) and through which the sidebar is pre-populated. If the users are already selected then they appear here exactly as they do in array-A.
My goal is to be able to add and remove objects from array-B / Sidebar view, by clicking on items from array-A in the main container.
The below is as close as I've been able to get but it doesn't take into account the existing users which are pre-populated onto the sidebar, and just adds and removes items that are already present, as if they weren't there.
For your reference:
$scope.selectedUsers = array-B
user = object in array-A
$scope.selectUser = function (user) {
console.log($scope.selectedUsers.indexOf(user))
if ($scope.selectedUsers.indexOf(user) === -1 ) {
$scope.selectedUsers.push(user);
console.log($scope.selectedUsers);
} else {
$scope.selectedUsers.splice($scope.selectedUsers.indexOf(user), 1);
console.log($scope.selectedUsers);
}
};
I really have no idea as to how to approach a solution for this, would really appreciate any help possible.
Thanks.
Use Array.prototype.reduce to check users before adding:
$scope.add = function(user){
var match = $scope.selectedUsers.reduce(function(prev, curr) {
return (user.id === curr.id) || prev;
}, false);
console.log(match ? 'match' : 'no match');
if (!match) $scope.selectedUsers.push(user);
};
... where your view looks like:
<p ng-repeat="user in users">{{user.username}} <a ng-click="add(user)">+</a></p>
To remove users from the selectedUsers array, use Array.prototype.splice:
$scope.remove = function(index){
$scope.selectedUsers.splice(index, 1)
}
...where your view looks like:
<p ng-repeat="selectedUser in selectedUsers">{{selectedUser.username}}
<a ng-click="remove($index)">--</a></p>
Working Plunker
Since it appears that each of your objects has a unique string ID, a viable approach is to store only the IDs in array-A and array-B, store a dictionary of the full data objects in a shared service, and use an angular filter to look up the full data object by ID when needed for presentation, etc.

Categories

Resources