I'm creating a project / to-do appliction with firestore. I want to return all the current projects where the active user has been assigned to.
In a console.log(doc.id, doc.data())
, I get the two projects where he has been signed up for.
But when I want to show them both on the home screen, I only see one project.
I don't know what I'm doing wrong Anyone that can help me?
My function:
const returnProjects = async () => {
const list = document.querySelector<HTMLDivElement>('#projectList');
const projects = query(collectionGroup(db, 'projects'));
const querySnapshot = await getDocs(projects);
querySnapshot.forEach((doc) => {
const deadline = doc.data().Deadline;
const fireBaseTime = new Date(
deadline.seconds * 1000 deadline.nanoseconds / 1000000,
);
const formatOptions = {
format: 'dd MMM yy',
};
console.log(doc.id, '>', doc.data());
const newElemement = document.createElement('div');
if (list) list.appendChild(newElemement).setAttribute('class', 'projectCard');
const card = document.querySelector<HTMLDivElement>('.projectCard');
if (card) { card.innerHTML = `
<h4>${doc.id, doc.data().Name}</h4>
<p>${fireBaseTime.toLocaleDateString('eng-BE', formatOptions)}</p>
<span>3</span>
`; }
});
};
my Html:
<main>
<div id="dashboard" >
<div class='dashboardUtils'>
<h3 id="dashboardName"></h3>
<span id="currentDate"></span>
</div>
<button id="editDashboard" ></button>
</div>
<div id='dashboardEdits-form' >
<form id='dashboardEdits' class='edit-form'>
<div id='practicalDisplayname'>
<label for='displayname' class='form-label'>Username</label>
<input type='text' class='form-input' id="displaynameInput" name='displayname'></input>
</div>
</form>
<button id="confirmEdits" >Save edits</button>
</div>
<div id='amountMessage'>
<h1 id='amountProjects'></h1>
</div>
<div id='projectList'></div>
</main>
CodePudding user response:
The problem is that for each document in the results you do:
const card = document.querySelector<HTMLDivElement>('.projectCard');
if (card) { card.innerHTML = `
<h4>${doc.id, doc.data().Name}</h4>
<p>${fireBaseTime.toLocaleDateString('eng-BE', formatOptions)}</p>
<span>3</span>
`; }
While you're creating a new project card for each result, the querySelector
always returns the first card for the HTML. From the MDN documentation on querySelector
:
An Element object representing the first element in the document that matches
So for the second document, you're replacing the innerHTML
that you set for the first document.
To solve the problem, since you already have a reference to the element you just generated, add the innerHTML
to that instead of looking it up with a query selector:
querySnapshot.forEach((doc) => {
...
const newElement = document.createElement('div');
if (list) list.appendChild(newElemement).setAttribute('class', 'projectCard');
newElement.innerHTML = `
<h4>${doc.id, doc.data().Name}</h4>
<p>${fireBaseTime.toLocaleDateString('eng-BE', formatOptions)}</p>
<span>3</span>
`;
})
CodePudding user response:
The problem you are facing here is caused by the following behavior:
What this means is that appendChild will remove the node if already present in the DOM, which is what we are seeing here. This can be easily solved by creating a deep clone of the node first using cloneNode, before appending it to the target div.