Skip to content
Advertisement

How can I get the specific user information from the list of users upon click in Javascript?

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:

  1. For each item, create a div element – document.createElement('div')
  2. Set its html similar to what you did – div.innerHTML
  3. 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>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement