I am writing a firebase mini chat web app where an admin can be able to privately chat with all the authenticated users.
so I used the firebase cloud-function to fetch the list of all users, code: π
//LISTING USERS FOR ADMIN
exports.listUsers = functions.https.onCall((data, context) => {
// check if user is admin (true "admin" custom claim), return error if not
const isAdmin = context.auth.token.admin === true
if (!isAdmin) {
return {
error: `Unauthorized.`
}
}
β
return admin.auth().listUsers().then((listUsersResult) => {
// go through users array, and deconstruct user objects down to required fields
const result = listUsersResult.users.map((user) => {
const {
uid,
email,
photoURL,
displayName,
disabled
} = user
return {
uid,
email,
photoURL,
displayName,
disabled
}
})
β
return {
result
}
})
.catch((error) => {
return {
error: 'Error listing users'
}
})
})
β
And from the front-end I called the cloud-function and displayed users using map method. π
const listUsers = functions.httpsCallable('listUsers');
listUsers().then(res => {
const result = res.data.result;
β
const output = result.map(item => {
return `<div class="user">
<img src="${item.photoURL}" />
<p class="username">${item.displayName}</p>
</div>`
});
β
listChats.innerHTML = output.join('');
})
β
Users are listed successfully. My problem now is if admin click on a specific user, I can be able to get or grab that specific user information like, id, displayName, etc.
thanks as you help me outπππ
Advertisement
Answer
You can bind a click
event only on a DOM element. There are some ways to do this even if you added the element with innerHTML
. But for simplicity, Iβd offer you to not add the elements with innerHTML
but with document.createElement
which returns the DOM element.
So the logic is:
- For each item, create a
div
element βdocument.createElement('div')
- Set its html similar to what you did β
div.innerHTML
- Bind it a click event β
div.addEventListener('click', ..)
This way, you have the item itself in the addEventListener
callbackβs scope. Thatβs why the alert
works.
function listUsers() {
return Promise.resolve({
data: {
result: [
{
photoURL: 'https://www.w3schools.com/howto/img_avatar.png',
displayName: 'john'
}
]
}
})
}
β
listUsers().then(res => {
const result = res.data.result;
β
result.forEach(item => {
const div = document.createElement('div');
div.classList.add('user');
div.innerHTML = `
<img src="${item.photoURL}" />
<p class="username">${item.displayName}</p>
`;
div.addEventListener('click', () => {
alert(JSON.stringify(item, null, 2));
});
listChats.appendChild(div);
});
β
listChats.innerHTML = output.join('');
})
<div id="listChats"></div>