I am trying to find a way to find the value of the id given the email.
For example, If I had email2#gmail.com, It would give me the ID 108454568498950432898.
All emails are unique and there will be no repetition of emails.
This is my user tree:
Note: In the image it says email2 instead of email2#gmail.com. Ignore this
Here's my code so far:
(Code won't run obviously but it's easier to enter code using the embed)
var users;
var givenEmail = "email2#gmail.com";
var neededID;
var dataRef = firebase.database().ref('users');
dataRef.on('value', (snapshot) => {
const data = snapshot.val();
users = data;
});
var usersArray = Object.keys(users);
for(i = 0; i < usersArray.length; i++) {
if(users[i].email == givenEmail) {
neededID = i;
break;
}
}
I recommend using a query to perform the filtering on the server, instead of downloading the entire users node and filtering in your application code as you now do.
var givenEmail = "email2#gmail.com";
var dataRef = firebase.database().ref('users');
var query = dataRef.orderByChild('email').equalTo(givenEmail);
dataRef.once('value', (snapshot) => {
snapshot.forEach((userSnapshot) => {
console.log(userSnapshot.val().id);
});
});
Well, I think you are almost there.
users[i].email
you can retrieve the email using this method, and similarly you can do it with id too
users[i].id
Please note that you wanted to find email2#gmail.com but your firebase only have email2
Maybe you would want to change that
Related
I´m trying to loop through the content of a DataSnapshot and then depending on a condition do some work FOR EACH one of the elements but currently, the ForEach is only doing the work in the first item. The "serverStatus" sometimes is waiting and sometimes in "onCall". When the first item is "onCall" does not go through the rest of the items as I think is supposed to do. Below a snapchot of where I get the information from:
And here is my function:
exports.manageCallRequests = functions.database.ref('/resquests/{userId}').onCreate((snap, context) => {
const event = snap.val();
console.log("function manageCallRequests is being called")
var rootPath = admin.database().ref();
var userOnCall = context.params.userId;
var serversRef = rootPath.child('servers');
var callRequest = event;
var userTime = callRequest["time"];
var waiting= "waiting";
//We first get all the servers in ascending order depending on the last time they were used
var serversSorted = serversRef.orderByChild('lastTimeUsed')
//Gets the children on the "serversSorted" Query
return serversSorted.once("value").then(allServers =>{
//Checks if there is any child
if(allServers.hasChildren()){
allServers.forEach(async function(server) {
//we extract the value from the server variable, this contains all the information
//about each one of the servers we have
var serverInfo = server.val();
var serverKey = server.key;
var serverNumber = serverInfo["serverNumber"];
var serverStatus = serverInfo["serverStatus"];
console.log("server status "+serverStatus)
if(serverStatus === waiting){
const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");
}
});
}else{
console.log("No servers available")
}
});
});
I had the same behavior because my cloud function was exited before that all iterations were executed in the forEach loop.I get rid of it using this snippet of code:
for (const doc of querySnapshot.docs) {
// Do wathever you want
// for instance:
await doc.ref.update(newData);
}
I found 2 ways of getting this done. The first one is useful if we have a DataSnapshot without any OrderBy* call, in this case, would be:
var allServers = await serversRef.once("value");
for (let serverKey of Object.keys(allServers.val())){
var server = allServers[serverKey];
//Do some work
}
We need to first get the keys of the object to then be able to extract it from within the for loop, as explained here otherwise we´ll get a "TypeError: 'x' is not iterable"
Now the problem with this particular case is that a have a DataSnapshot that was previously sorted at var serversSorted = serversRef.orderByChild('lastTimeUsed') so when we call Object.keys(allServers.val()) the value returned is no longer sorted and that´s where forEach() comes in handy. It guarantees the children of a DataSnapshot will be iterated in their query order as explained here however for some reasons when doing some async work within the forEach loop this seems not to work, that´s why I had to do this:
var serversSorted = serversRef.orderByChild('lastTimeUsed')
var allServers = await serversSorted.once("value");
//Checks if there is any children
if (allServers.hasChildren()) {
//if there is iterate through the event that was passed in containing all
// the servers
var alreadyOnCall = false;
var arrayOfServers = []
var arrayOfKeys = []
allServers.forEach(function(individualServer){
arrayOfKeys.push(individualServer.key)
arrayOfServers.push(individualServer)
})
for (var serveIndex = 0; serveIndex < arrayOfServers.length;serveIndex++){
var serverObj = arrayOfServers[serveIndex]
var serverObject = serverObj.val()
var serverKey = arrayOfKeys[serveIndex]
var serverStatus = serverObject["serverStatus"];
var serverNumber = serverObject["serverNumber"];
console.log("server info "+serverStatus+" "+serverKey);
if (serverStatus === waiting && alreadyOnCall === false) {
const setCallRequest = await serversRef.child(serverKey).child("current").child("callRequest").set(callRequest);
const removeUserOnCall = await rootPath.child("resquests").child(userOnCall).remove();
const setServerStatus = await serversRef.child(serverKey).child("serverStatus").set("onCall");
alreadyOnCall= true
console.log("Call properly set");
}
}
}
I tried to save my data in local Storage with setItem but when I refresh the chrome tab and add data to my array, the data in localStorage delete the old data and set new data instead of updating that old data.
Here is my code:
let capacity = 200;
let reservedRooms = 0;
let users = [];
let rsBox = document.getElementById('reservebox');
class Reserver {
constructor(name , lastName , nCode , rooms){
this.name = name ;
this.lastName = lastName ;
this.nCode = nCode ;
this.rooms = rooms ;
}
saveUser(){
if(this.rooms > capacity){
console.log('more than capacity');
}else{
users.push({
name : this.name ,
lastName : this.lastName ,
id : this.nCode ,
rooms : this.rooms
});
capacity -= this.rooms ;
reservedRooms += this.rooms ;
}
}
saveData(){
localStorage.setItem('list',JSON.stringify(users));
}
}
rsBox.addEventListener('submit',function(e){
let rsName = document.getElementById('name').value;
let rsLastName = document.getElementById('lastname').value;
let rsNationalCode = Number(document.getElementById('nationalcode').value);
let rooms = Number(document.getElementById('rooms').value);
//Save the user data
let sign = new Reserver(rsName , rsLastName , rsNationalCode , rooms);
sign.saveUser();
sign.saveData();
e.preventDefault();
});
You are pushing an empty users array each time you reload the page, to resolve this you need to populate the users array from the items you have in storage.
e.g.
let users = [];
needs to be something like
let users = JSON.parse(localStorage.getItem('list')) || [];
The key point being that you need to load your existing users to be able to add to them, if you don't then you are essentially creating the users array fresh each time the page loads and you put data into it.
You may want to create something like a "loadData" function that checks if the array is initialized, loads it if it is and creates it if it isn't. You can make this generic so that you can use it to access any key and provide a default value if the key isn't present e.g.
function loadData(key, def) {
var data = localStorage.getItem(key);
return null == data ? def : JSON.parse(data)
}
then
// load "list" - set to an empty array if the key isn't present
let users = loadData('list', []);
Another option would be to change the saveData method so you won't have to load the localStorage when the app is loading:
saveData(){
let newList = JSON.parse(localStorage.getItem('list') || '[]')
if(users.length) newList.push(users[users.length - 1]);
localStorage.setItem('list',JSON.stringify(newList));
newList=null;
}
Note: Be careful with localStorage because it doesn't have the same capacity on all browsers, you can check this post for more information
I am pretty new to Javascript, a couple of months in. Essentially, I am trying to make a simple online-based shared shopping-list for a class. I can add to the database, I can show the items as a list, right now my issue is how to remove. I have given the buttons the keys of the database entry they are attached to, as ID, hoping that that would work, but I can't find a way to use the ID. As you can see, i've been testing it by seeing if I can console.log the key, but no luck so far. I've seen a dozen videos and tried dozens of guides, and I hope you can help me; How to I make it so when I click the button, the corresponding entry in the database is deleted? Sorry that the code is a bit of a mess, right now, it is mostly strung together from old code and guides.
var database = firebase.database();
var ref = database.ref('Varer');
ref.on('value', gotData, errData);
function gotData(data){
document.getElementById('Liste').innerHTML = "";
var kbdt = data.val();
var keys = Object.keys(kbdt);
for (var i = 0; i < keys.length; i++){
var k = keys[i];
var kob = kbdt[k].varer;
var btn = document.createElement('button');
var btnText = document.createTextNode('Done')
var opg = document.createElement('li');
var opgnvn = document.createTextNode(kob);
opg.appendChild(opgnvn);
btn.appendChild(btnText);
opg.appendChild(btn);
opg.setAttribute('id', k);
opg.setAttribute('class', 'button');
document.getElementById('Liste').append(opg);
btn.addEventListener('click', function(){
deleteTask(this.id)});
}
}
function errData(err){
console.log('error!');
console.log(err);
}
function deleteTask(id) {
console.log(id);
}
function Indkob() {
var nyVare = document.getElementById('tilfoj').value;
document.getElementById('Liste').innerHTML = "";
var data = {
varer: nyVare
}
var result = ref.push(data);
console.log(result.keys);
}
If I use limitToLast(1), then I still get an object, with one key-value pair. To get the value, I use this code:
db.ref('/myarray').limitToLast(1).once('value').then(function(snapshot) {
var result = snapshot.val();
var lastElem;
var lastKey;
for(var i in result) {
lastElem= result[i];
lastKey = i;
break;
}
...
});
It works, but I think I do it wrong. But haven't found any better solution in the docs. How should I load only one element?
The database looks like this:
When using Firebase queries to get children, use the "child_added" event:
db.ref("/myarray")
.orderByKey() // order by chlidren's keys
.limitToLast(1) // only get the last child
.once("child_added", function(snapshot) {
var key = snapshot.key;
var val = snapshot.val();
...
});
Can anyone help me to get the user info from a person column using javascript? So far I have been able to read the list item and return a SP.FieldUserValue from which I can get a numeric Id (not sure what this ID is) and the display name. e.g.
var ManVal = oListItem.get_item("RecruitingManager").get_lookupValue();
var ManId = oListItem.get_item("RecruitingManager").get_lookupId();
How do I take this one step further to create a sp user object?
Ultimately what I'm trying to achieve is to retrieve the details from the list and then populate a people editor.
Ok, I've got it.
Here is my code, hope it helps somebody. I haven't included the method to retrieve the list item, just the line from that function where I'm getting the value of the person.
var _lineManager;
var lineManager = oListItem.get_item("RecruitingManager").get_lookupId();
_lineManager = oWebsite.getUserById(lineManager);
getLineManager();
function getLineManager() {
context.load(_lineManager);
context.executeQueryAsync(onGetUserNameSuccessLM, onGetUserNameFailLM);
}
function onGetUserNameSuccessLM() {
alert(lineManager.get_title());
var schema = {};
schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
schema['SearchPrincipalSource'] = 15;
schema['ResolvePrincipalSource'] = 15;
schema['AllowMultipleValues'] = false;
schema['MaximumEntitySuggestions'] = 50;
schema['Width'] = '280px';
var users = new Array(1);
var defaultUser = new Object();
defaultUser.AutoFillDisplayText = lineManager.get_title();
defaultUser.AutoFillKey = lineManager.get_loginName();
defaultUser.Description = lineManager.get_email();
defaultUser.DisplayText = lineManager.get_title();
defaultUser.EntityType = "User";
defaultUser.IsResolved = true;
defaultUser.Key = lineManager.get_loginName();
defaultUser.Resolved = true;
users[0] = defaultUser;
SPClientPeoplePicker_InitStandaloneControlWrapper('peoplePickerDivLinMan', users, schema);
}
function onGetUserNameFailLM(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
The person field (actually called "people picker") has a specific JavaScript function which you might find useful: GetAllUserInfo()
There is a nice article on MSDN:
How to: Use the client-side People Picker control in apps for SharePoint
The relevant code is:
// Get the people picker object from the page.
var peoplePicker = this.SPClientPeoplePicker.SPClientPeoplePickerDict.peoplePickerDiv_TopSpan;
// Get information about all users.
var users = peoplePicker.GetAllUserInfo();
var userInfo = '';
for (var i = 0; i < users.length; i++) {
var user = users[i];
for (var userProperty in user) {
userInfo += userProperty + ': ' + user[userProperty] + '<br>';
}
}
$('#resolvedUsers').html(userInfo);
// Get user keys.
var keys = peoplePicker.GetAllUserKeys();
$('#userKeys').html(keys);
So basically you have to cast your field to a SPClientPeoplePicker and can then use GetAllUserInfo to iterate over all users in the field.