Firebase database snapshot is not working? - javascript

I am trying to implement a simple search through firebase database. the logic is that
When A value is entered in the search box, go to database path of the entered value and get a snapshot value at the directory. for some reason, I have been stuck on this with the error listed below and I don't know what is causing it.
<form class="search" action="">
<input type="search" id="search-input" placeholder="Enter NSN number here..." required>
<button class="Init_search" id="findbutton">Search</button>
</form><br /><br />
the search result is displayed here
<div class="container"><br /><br />
<ul class="collapsible" data-collapsible="expandable" id="searchresult">
</ul>
</div>
this is my js code
document.getElementById("findbutton").addEventListener("click", function(e){
var FindNSN = document.getElementById('search-input').value;
firebase.auth().onAuthStateChanged((user) => {
if (user) {
database = firebase.database();
var uid = firebase.auth().currentUser.uid;
console.log(FindNSN);
var searchref = database.ref('/Businesses/' + uid + '/Inventory/' + FindNSN);
searchref.on('value', search, errData); // this is dashboard.js:363
}
})
})
function search(data){
var container = document.getElementById('searchresult');
var uid = firebase.auth().currentUser.uid;
container.innerHTML = '';
data.forEach(function(SearchSnap) {
var key = SearchSnap.key;
var Results = SearchSnap.val();
console.log(Results);
var ResultCard = `
<li>
<div class="collapsible-header"><i class="mdi-navigation-chevron-right"></i><a name="987"/>${Results.ProductName}</a></div>
<div class="collapsible-body"><p>${Results.ProductDescription}</p></div>
</li>
`;
container.innerHTML += ResultCard;
})
}
this is the error I keep getting
Uncaught (in promise) Error: Query.on failed: Second argument must be a valid function.
at A (firebase-database.js:44)
at U.g.gc (firebase-database.js:170)
at firebase.auth.onAuthStateChanged (dashboard.js:363)
at firebase-auth.js:202
at <anonymous>
A # firebase-database.js:44
g.gc # firebase-database.js:170
firebase.auth.onAuthStateChanged # dashboard.js:363
(anonymous) # firebase-auth.js:202
the error is saying second argument is not a valid function. i was able to narrow it down the search() but i cant see what makes the function invalid.
What am I doing wrong and How can I fix it?

Related

Trying to move completed tasks from one list to another

Here we have a tab with incompled tasks and the list is supposed to be attached to the first tab(all-taks). After the task is finished it is supposed to get deleted from first list and move to second one with completed tasks. And after you switch to second tab, all the completed ones should be there. I can't figure out the way to do it.
I hope I could get some help or some detailed explanation, 'cause I have been stuck on this for some time.
Here is an image for more clarification:
[1]: https://i.stack.imgur.com/Dy0KL.png
HTML code:
<body>
<div class="container">
<header>
<h1>To-Do List</h1>
<h4>Describe your list...</h4>
</header>
<form action="" class="todo-form">
<div class="form-wrapper">
<!-- action is where files will be sent after submitting -->
<input class="todo-input" type="text" placeholder="Add a task...">
</div>
<div class="form-wrapper">
<button class="todo-button" type="submit">Add</button>
</div>
</form>
<div class="todo-tabs">
<ul>
<li class="all-tasks active">
<span></span>All tasks (<span class="counter">0</span>)</span>
</li>
<li class="completed">
<span>Completed (<span class="counter">0</span>)</span>
</li>
</ul>
</div>
<div class="todo-list">
<div class="tabs-content" data-tab="1">
<ol class="undone-tasks"></ol>
</div>
<div class="tabs-content" data-tab="2">
<ol class="done-tasks"></ol>
</div>
</div>
</body>
JS code:
//Selectors
const todoForm = document.querySelector('.todo-form');
const todoInput = document.querySelector('.todo-input');
const todoButton = document.querySelector('.todo-button');
const tabs = document.querySelectorAll('.todo-tabs ul li');
const tabWrap = document.querySelector('.todo-tabs ul');
const undone = document.querySelector('.undone-tasks');
const done = document.querySelectorAll('.done-tasks');
//Event Listeners
tabWrap.addEventListener('click', tabs)
todoButton.addEventListener('click', addToDo);
//Functions
tabs.forEach(function (tab, tab_index) {
tab.addEventListener("click", function () {
tabs.forEach(function (tab) {
tab.classList.remove("active");
})
tabWrap.forEach(function (todoList, todoList_index) {
if (todoList_index == tab_index) {
todoList.style.display = "block";
}
else[
todoList.style.display = "none"
]
})
})
})
function addToDo(event) {
//Prevent form from submitting
event.preventDefault();
if (todoInput.value != "") {
const todoDiv = document.createElement('div');
todoDiv.classList.add('todo-div');
const inputCheckbox = document.createElement('input');
inputCheckbox.classList.add("checkbox-incompleted");
inputCheckbox.setAttribute('type', 'checkbox');
todoDiv.appendChild(inputCheckbox);
//Create li
const newToDo = document.createElement('li');
newToDo.classList.add('todo-item');
newToDo.insertAdjacentText("beforeend", todoInput.value);
todoDiv.appendChild(newToDo);
console.log(newToDo)
//Append to list
undone.appendChild(todoDiv);
//Clear todo input value
todoInput.value = "";
//Focusing after 1st input
todoInput.focus();
}
}
The commented area is what i tried to do for tabs and lists to switch, but it gives the following error:
Uncaught TypeError: tabWrap.forEach is not a function
at HTMLLIElement.<anonymous> (script.js:32:17)
(anonymous) # script.js:32
The error starts at the beggining of the tabWrap.forEach function. But I guess there could be other way to solve this
tabWrap is not useful for what you want: it is a single element. Instead, you'll want to iterate over the tab contents, which are identified by class tabs-content. It is those that you need to iterate and show or hide.
Then, to decide which contents to use, you may need to use that data-tab attribute you have in your HTML (not sure, since it is nowhere referenced).
Anyway, adapt as needed:
const tabContents = document.querySelectorAll('.tabs-content');
tabs.forEach(function (activeTab, activeIndex) {
activeTab.addEventListener("click", function (e) {
tabs.forEach(function (tab) {
tab.classList.toggle("active", tab == activeTab);
});
tabContents.forEach(function (tabContent) {
tabContent.style.display = tabContent.dataset.tab == activeIndex + 1 ? "" : "none";
});
})
})
As #Anurag Srivastava pointed out on comment, in your code this is how you get tab elements:
const tabs = document.querySelectorAll('.todo-tabs ul li');
const tabWrap = document.querySelector('.todo-tabs ul');
The method querySelector returns a single element, and querySelectorAll returns an iterable collection.
And this is why you're getting the error:
Uncaught TypeError: tabWrap.forEach is not a function
If you don't have to support internet explorer you could take a look at Element.insertAdjacentElement() to move elements from one tab to another.

How to get value from dynamically generated <option> <select> express ejs

First of all I thank you for reading and making an attempt to my problem.
I dynamically rendered my {dropdown} but i was unable to get the selected value at my back-end.
on my form i am also getting photo and the name of suite is dynamically rendered.
Code below if i am doing something incorrect.
Lang - Javascript
FW - Express Js
Template - EJS
I have body-parse and set to true.
Issue i cannot get selected value to my back-end using POST request (undefined or null).
But if i use GET as the action & Request i do get the selected value.
Thank you again. If i am not clear please, i will explain clearly. I am newly NODE JS AND EXPRESS.
-Front-end
<form class="ui form" action="admin/uploadphoto" method="POST" enctype="multipart/form-data">
<h2 class=" ui dividing header" style="text-align: center;">Add Images to suites</h2>
<div class="two fields">
<div class="field">
<label>Add Suites Images</label>
<input name="suiteimage" type="file">
</div>
<div class="field">
<label>Suites*</label>
<select name="suiteselected" class="ui dropdown">
<% suites.forEach(function(suite) { %>
<option name = "suiteid" value="<%= suite.suite_name %>"><%= suite.suite_name %></option>
<% })%>
</select>
</div>
</div>
<input type="submit" class="ui button" tabindex="0" value="Save New Suite">
</form>
Back-end
const uuid = require("uuid/v4");
const { Pool } = require("pg");
const multer = require("multer");
// Insert photo and selected value from dropdown (options)
const PostPhoto = (req, res) => {
var suiteimage;
const suite_photo_id = uuid();
const {suiteselected} = req.body;
console.log( suiteselected + " --ID") //Here i am testing if selected valued is passed
// this is my multer function to config where i need to store my photo path
upload(req, res, err => {
suiteimage = req.file.path;
if (err) {
console.log(err);
} else {
console.log(suiteimage);
}
});
..... //my database query to save my post....
};
-route
router.post ('/uploadphoto', service.PostPhoto);
``
I have figured out the solution to this, body-parse should be required and extended true.
when having text and image as 1 form to be posted to the back-end make sure
Your image function (upload) is inside the req,res function or the values will be undefine or null.
if you need more explanation to comment.
//my post for image and text function
const PostPhoto = (req, res) => {
const suite_photo_id = uuid();
upload(req, res, function(err) {
const {suiteselected} = req.body;
console.log(req.file);
var imagePath = req.file.path.replace(/^public\//, '');
console.log( suiteselected + " --ID")
console.log(imagePath);
pool.query(
"INSERT INTO suite_photos (suite_photo_id,suite_photo,suite_id) VALUES($1,$2,$3)",
[suite_photo_id, imagePath,suiteselected],
(error, result) => {
if (error) {
throw error;
} else{
console.log(result);
res.redirect("/admin");
}
}
);
});
};
That's all that changed.
Thank you all!!!

PubNub ChatEngine "Converting circular structure to JSON" error after joining back to 1-1 chat using Angular

I'm trying to wrap my head around this PubNub ChatEngine example using Angular for first time https://github.com/pubnub/chat-engine-examples/tree/master/angular/simple
In demo when you click on user from the list new channel with random name is generated and user invited to it. So if you leave chat click on user again you connect to new channel.
I'm trying to do 1-1 chat rooms, that you could leave than join back, so changed channel name to be clicked user uuid. Now if I leave the channel, join back to it and try to send message it's not being shown in list, though it's being sent and user you are chatting with receives it.
In console I'm getting "Uncaught (in promise) TypeError: Converting circular structure to JSON" when starting to type (as have chat engine typing indicator running) and after submit.
I guess that's something to do with removing chat from global scope using splice() method and after joining back new chat being added. It works in demo because there are getting new channel each time and removing it, but not if using same channel now.
I tried to use splice() instead to see what happens. If I close chat and join back to it, it stays in DOM, and new one is added to scope, so have two same chat elements in DOM. If I type and send message on second one, it's not being displayed at it, but instead on first one that tried to close.
How could I get this working properly, can splice() be used in my case and I'm missing something else that is causing the error?
$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
//$scope.chats.slice(index, 1);
//$scope.chats.splice( $scope.chats.indexOf($scope.chat), 1 );
}
angular.module('chatApp', ['open-chat-framework'])
.run(['$rootScope', 'ngChatEngine', function($rootScope, ngChatEngine) {
$rootScope.ChatEngine = ChatEngineCore.create({
publishKey: 'pub-c-d8599c43-cecf-42ba-a72f-aa3b24653c2b',
subscribeKey: 'sub-c-6c6c021c-c4e2-11e7-9628-f616d8b03518'
}, {
debug: true,
globalChannel: 'chat-engine-angular-simple'
});
// bind open chat framework angular plugin
ngChatEngine.bind($rootScope.ChatEngine);
// set a global array of chatrooms
$rootScope.chats = [];
}])
.controller('Chat', function($scope) {
$scope.chat.plugin(ChatEngineCore.plugin['chat-engine-typing-indicator']({
timeout: 5000
}));
// every chat has a list of messages
$scope.messages = [];
// we store the id of the lastSender
$scope.lastSender = null;
// leave a chatroom and remove from global chat list
$scope.leave = (index) => {
$scope.chat.leave();
$scope.chats.splice(index, 1);
}
// send a message using the messageDraft input
$scope.sendMessage = () => {
$scope.chat.emit('message', {
text: $scope.messageDraft
});
$scope.messageDraft = '';
}
// when we get notified of a user typing
$scope.chat.on('$typingIndicator.startTyping', (event) => {
event.sender.isTyping = true;
});
// when we get notified a user stops typing
$scope.chat.on('$typingIndicator.stopTyping', (event) => {
event.sender.isTyping = false;
});
// function to add a message to messages array
let addMessage = (payload, isHistory) => {
// if this message was from a history call
payload.isHistory = isHistory;
// if the last message was sent from the same user
payload.sameUser = $scope.messages.length > 0 && payload.sender.uuid == $scope.messages[$scope.messages.length - 1].sender.uuid;
// if this message was sent by this client
payload.isSelf = payload.sender.uuid == $scope.me.uuid;
// add the message to the array
$scope.messages.push(payload);
}
// if this chat receives a message that's not from this sessions
$scope.chat.search({
event: 'message'
}).on('message', function(payload) {
// render it in the DOM with a special class
addMessage(payload, true);
})
// when this chat gets a message
$scope.chat.on('message', function(payload) {
// render it in the DOM
addMessage(payload, false);
});
})
.controller('OnlineUser', function($scope) {
// create a new chat
$scope.newChat = function(user) {
// define a channel
let chan = user.uuid;
// create a new chat with that channel
let newChat = new $scope.ChatEngine.Chat(chan);
// we need to auth ourselves before we can invite others
newChat.on('$.connected', () => {
// this fires a private invite to the user
newChat.invite(user);
// add the chat to the list
$scope.chats.push(newChat);
});
};
})
.controller('ChatAppController', function($scope) {
// create a user for myself and store as ```me```
$scope.ChatEngine.connect(new Date().getTime(), {}, 'auth-key');
$scope.ChatEngine.on('$.ready', (data) => {
$scope.me = data.me;
$scope.me.plugin(ChatEngineCore.plugin['chat-engine-random-username']($scope.ChatEngine.global));
$scope.ChatEngine.global.plugin(ChatEngineCore.plugin['chat-engine-online-user-search']());
// when I get a private invit
$scope.me.direct.on('$.invite', (payload) => {
let chat = new $scope.ChatEngine.Chat(payload.data.channel);
chat.onAny((a,b) => {
console.log(a)
});
// create a new chat and render it in DOM
$scope.chats.push(chat);
});
// bind chat to updates
$scope.chat = $scope.ChatEngine.global;
// hide / show usernames based on input
$scope.userSearch = {
input: '',
fire: () => {
// get a list of our matching users
let found = $scope.ChatEngine.global.onlineUserSearch.search($scope.userSearch.input);
// hide every user
for(let uuid in $scope.chat.users) {
$scope.chat.users[uuid].hideWhileSearch = true;
}
// show all found users
for(let i in found) {
$scope.chat.users[found[i].uuid].hideWhileSearch = false;
}
}
};
$scope.userAdd = {
input: '',
users: $scope.userAdd,
fire: () => {
if($scope.userAdd.input.length) {
$scope.userAdd.users = $scope.ChatEngine.global.onlineUserSearch.search($scope.userAdd.input);
} else {
$scope.userAdd.users = [];
}
}
};
});
});
<div class="container-fluid" ng-controller="ChatAppController">
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-block">
<h4 class="card-title">ChatEngine</h4>
<p class="card-text">Your are {{me.state.username}} with uuid {{me.uuid}}</p>
</div>
<ul id="online-list" class="list-group list-group-flush">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
{{user.state.username}}
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<form class="send-message" ng-submit="userSearch.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Search for Username" ng-change="userSearch.fire()" ng-model="userSearch.input">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Search</button>
</span>
</div>
</form>
</div>
</div>
</div>
<div class="col-md-6">
<div id="chats" class="row" ng-repeat="chat in chats" ng-controller="Chat">
<div class="chat col-xs-12">
<div class="card">
<div class="card-header">
<div class="col-sm-6">
{{chat.channel}}
</div>
<div class="col-sm-6 text-right">
x
</div>
</div>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in chat.users" ng-hide="user.hideWhileSearch" ng-controller="OnlineUser">
{{user.state.username}}
<span class="show-typing" ng-show="user.isTyping">is typing...</span>
</li>
</ul>
<div class="card-block">
<div class="log">
<div ng-repeat="message in messages" ng-class="{'hide-username': message.sameUser, 'text-muted': message.isHistory, 'text-xs-right': !message.isSelf}">
<p class="text-muted username">{{message.sender.state.username}}</p>
<p>{{message.data.text}}</p>
</div>
</div>
<p class="typing text-muted"></p>
<form class="send-message" ng-submit="sendMessage(chat)">
<div class="input-group">
<input ng-model="messageDraft" ng-change="chat.typingIndicator.startTyping()" type="text" class="form-control message" placeholder="Your Message...">
<span class="input-group-btn">
<button class="btn btn-primary" type="submit">Send</button>
</span>
</div>
</form>
</div>
<hr />
<div class="card-block">
<h6>Add a user to this chat</h6>
<fom ng-submit="userAdd.fire()">
<div class="input-group">
<input id="usernameSearch" type="text" class="form-control message" placeholder="Add User" ng-change="userAdd.fire()" ng-model="userAdd.input">
</div>
</form>
<ul class="list-group list-group-flush online-list-sub">
<li class="list-group-item" ng-repeat="(uuid, user) in userAdd.users" ng-controller="OnlineUser">
{{user.state.username}}
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Issue is resolved by upgrading to the latest ChatEngine version. As per the ChatEngine github repo issue:
it's working correctly with chat-engine#0.9.5, I was using chat-engine#0.8.4

jQuery Search Function

Hi i'm building a project which has a page navigation and search bar in jQuery.
I can't get my search function to work correctly and I'm not certain if it's a problem with the ID element or the each function. I'm getting the ("Sorry, no student's found!") message for anything that is or isn't a match. So i think there could be a problem with the if statement looking for a match in search function--but not sure.
I'm dynamically adding a search box to my html like this:
function appendSearchBox(){
var search = "<div class='student-search'><input id='search' placeholder='Search for students...'><button>Search</button></div>"
$(".students").after(search);
// Add click event handler
$("button").click(function() {
searchList();
});
}
this is what my html looks like for a list of students:
<div class="page">
<div class="page-header cf">
<h2 class="students">Students</h2>
</div>
<ul class="student-list">
<li class="student-item cf">
<div class="student-details">
<img class="avatar" src="https://randomuser.me/api/portraits/thumb/women/67.jpg">
<h3>iboya vat</h3>
<span class="email">iboya.vat#example.com</span>
</div>
<div class="joined-details">
<span class="date">Joined 07/15/15</span>
</div>
</li>
</ul>
And then here is the actual search function:
var listStudents = $(".student-list li");
var numStudents = listStudents.length;
function searchList() {
var matched = [];
// Obtain the value of the search input
input = $("#search").val()
// remove the previous page link section
$('.pagination').hide();
// Loop over the student list, and for each student…
listStudents.each(function(){
// ...obtain the student’s name…
var name = $(this).find("h3").val();
// ...and the student’s email…
var email = $(this).find(".email").val();
// ...if the search value is found inside either email or name…
if (name.includes(input) || email.includes(input)) {
// ...add this student to list of “matched” student
matched.push($(this).parent());
}
});
// If there’s no “matched” students…
if (matched.length === 0){
// ...display a “no student’s found” message
var message = ("Sorry, no student's found!");
$(".student-list").hide();
$(".student-list").after(message);
if (matched.length > 10) {
// ...call appendPageLinks with the matched students
appendPageLinks(matched);
}
// Call showPage to show first ten students of matched list
showPage(1, matched);
}
}
adding functions which actually show the students and add navigation
function showPage(pageNum, listStudents) {
// first hide all students on the page
pageNum = parseInt(pageNum);
listStudents.hide();
// Then loop through all students in our student list argument
listStudents.each(function(index){
// if student should be on this page number
if ((index >= ((pageNum*10)-9)) && (index <= (pageNum*10))) {
// show the student
$(this).show();
}
});
}
function getNumPages(numStudents){
numPages = Math.ceil(numStudents/10);
return numPages;
}
function appendPageLinks(numStudents) {
// determine how many pages for this student list
pages = getNumPages(numStudents);
// create a page link section
var nav = "<div class='pagination'><ul>"
for (i=1; i<pages+1; i+=1){
nav += ("<li>" + "" + i + "" + "</li>");
};
nav += ("</ul></div>");
$(".student-list").after(nav);
// define what happens when you click a link
var active = $('.pagination a').click(function(){
// Use the showPage function to display the page for the link clicked
var id = $(this).attr('id');
showPage(id,listStudents);
// mark that link as “active”
active.removeClass('active');
$(this).addClass("active");
});
}
here is how i am calling the functions:
appendSearchBox();
showPage(1, listStudents);
appendPageLinks(numStudents);
UPDATE -- I have changed the code to remove the val and put in to grab the text.
Not sure what issue is but it appears if i have a correct match--it is working (since pagination disappears) but the students do not change on the page. If there is no match then I get the error message, but the error console is saying
Uncaught TypeError: listStudents.hide is not a function
at showPage (main.js:8)
I'm not sure if this is somehow related to how I am passing the 'matched' list?
h3 and span tags have no value, but text content, so replace:
var name = $(this).find("h3").val();
// ...and the student’s email…
var email = $(this).find(".email").val();
with:
var name = $(this).find("h3").text();
// ...and the student’s email…
var email = $(this).find(".email").text();
You are using val() method to read inner text of h3 and span (email). It should be text(). Also you are appending message after the student list every time you couldn't find a student. You could have used one span tag and hide/show based on the search results.
function appendSearchBox() {
var search = "<div class='student-search'><input id='search' placeholder='Search for students...'><button>Search</button></div>"
$(".students").after(search);
// Add click event handler
$("button").click(function () {
searchList();
});
}
$(document).ready(function () {
appendSearchBox();
});
function searchList() {
var listStudents = $(".student-list li");
var numStudents = listStudents.length;
$(".student-list").show();
$("#message").hide();
var matched = [];
// Obtain the value of the search input
input = $("#search").val()
// remove the previous page link section
$('.pagination').hide();
// Loop over the student list, and for each student…
listStudents.each(function () {
// ...obtain the student’s name…
var name = $(this).find("h3").text();
// ...and the student’s email…
var email = $(this).find(".email").text();
// ...if the search value is found inside either email or name…
if (name.includes(input) || email.includes(input)) {
// ...add this student to list of “matched” student
matched.push($(this).parent());
}
});
// If there’s no “matched” students…
if (matched.length === 0) {
// ...display a “no student’s found” message
var message = ("Sorry, no student's found!");
$(".student-list").hide();
$("#message").show();
if (matched.length > 10) {
// ...call appendPageLinks with the matched students
appendPageLinks(matched);
}
// Call showPage to show first ten students of matched list
showPage(1, matched);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="page">
<div class="page-header cf">
<h2 class="students">Students</h2>
</div>
<ul class="student-list">
<li class="student-item cf">
<div class="student-details">
<img class="avatar" src="https://randomuser.me/api/portraits/thumb/women/67.jpg">
<h3>iboya vat</h3>
<span class="email">iboya.vat#example.com</span>
</div>
<div class="joined-details">
<span class="date">Joined 07/15/15</span>
</div>
</li>
</ul>
<span id="message" style="display:none;"><br/>Sorry, no student's found!</span>
</div>

Retrieving user data from Firebase

I can't figure out what I'm doing wrong. The user name in Firebase is not being retrieved and updated.
This is my HTML:
<div class="header">
<div class="userPanel">
<div class="pic"></div>
<div class="welcome"><span>Welcome</span><h1 class="name" id="firstname">John</h1></div>
</div>
<div class="title"></div>
JS code:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log(user.uid);
var userRef = firebase.database().ref().child('Users')
var uid = user.uid;
var firstname = document.getElementById('firstname');
firebase.database().ref('Users/' + uid).on('value', function(snapshot){
var firstname.innerHTML = snapshot.val().Firstname;
});
Looks like the uid is undefined in the screenshot of your Firebase database. I'm guessing the user.uid you console.log is not undefined. What is output in your console?
Also, take out var in var firstname.innerHTML. You're not declaring a new variable called firstname.innerHTML.

Categories