'Node Project: EJS rendering white space before text retrieved from MongoDB
Good morning.
I am working in my first real development project using Node/MongoDB stack.
Everything is working as expected except by rendering text in EJS engine when I retrieve a string from DB to show in the page: the text is shown with a lot of white spaces in front of it.
I am trimming the text before sending it to the DB, directly in the model. I also tried to trim the text after retrieving it, with no luck.
What makes me believe the problem is with EJS its the fact that the text, on MongoDB doesn't has any trailing white spaces, but it has in the HTML seen in the browser inspect window.
I've searched through a lot of questions related to undesired white spaces, but did not found anything that could help me, so here I am asking for help, which would be very appreciated.
Thank you in advance!
This is how the text is rendered:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus gravida sem libero. Phasellus convallis tellus vitae imperdiet aliquam. Cras sollicitudin maximus augue, sit amet tincidunt felis. Mauris bibendum sollicitudin iaculis. Fusce eget magna tincidunt, porta lorem eu, semper nunc. Morbi at commodo mi. Aliquam feugiat, sem fringilla imperdiet porta, est nisl ultricies mauris, sed finibus orci odio eget quam. Praesent odio ex, suscipit luctus tempus posuere, suscipit ut nisi. Ut feugiat, velit vitae laoreet malesuada, ligula augue vulputate ligula, ut vulputate sapien neque ut dolor. Maecenas congue enim at nisi porttitor cursus. Etiam convallis neque vel urna molestie, et aliquet tortor congue...
This is how it appears in the Inspect Window:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus gravida sem libero. Phasellus convallis tellus vitae imperdiet aliquam. Cras sollicitudin maximus augue, sit amet tincidunt felis. Mauris bibendum sollicitudin iaculis. Fusce eget magna tincidunt, porta lorem eu, semper nunc. Morbi at commodo mi. Aliquam feugiat, sem fringilla imperdiet porta, est nisl ultricies mauris, sed finibus orci odio eget quam. Praesent odio ex, suscipit luctus tempus posuere, suscipit ut nisi. Ut feugiat, velit vitae laoreet malesuada, ligula augue vulputate ligula, ut vulputate sapien neque ut dolor. Maecenas congue enim at nisi porttitor cursus. Etiam convallis neque vel urna molestie, et aliquet tortor congue.
Nullam suscipit dui turpis, non porta odio egestas at. Sed eu ex tristique, facilisis massa sit amet, eleifend erat. Curabitur eu tempus tellus, sed lacinia nunc. Sed aliquam gravida porta. Vivamus eu luctus leo. Vestibulum condimentum arcu sem, vitae vehicula ligula ultrices eget. Fusce pretium molestie pellentesque. Nam ultrices mattis sapien ut consectetur. Cras et vehicula felis. Suspendisse quis egestas nunc, id tempor tellus. Proin placerat accumsan tristique.
</p>
Here is how it is in MongoDB:
{
_id: ObjectId("624c9293e176a46912503d36"),
title: 'Teste Novo Layout',
ages: '3-7',
sensiblePeriod: 'Matemática',
category: 'Visualização de Dados',
theme: 'Testagem',
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus gravida sem libero. Phasellus convallis tellus vitae imperdiet aliquam. Cras sollicitudin maximus augue, sit amet tincidunt felis. Mauris bibendum sollicitudin iaculis. Fusce eget magna tincidunt, porta lorem eu, semper nunc. Morbi at commodo mi. Aliquam feugiat, sem fringilla imperdiet porta, est nisl ultricies mauris, sed finibus orci odio eget quam. Praesent odio ex, suscipit luctus tempus posuere, suscipit ut nisi. Ut feugiat, velit vitae laoreet malesuada, ligula augue vulputate ligula, ut vulputate sapien
neque ut dolor. Maecenas congue enim at nisi porttitor cursus. Etiam convallis neque vel urna molestie, et aliquet tortor congue.\r\n' +
' \r\n' +
' \r\n' +
' \r\n' +
' Nullam suscipit dui turpis, non porta odio egestas at. Sed eu ex tristique, facilisis massa sit amet, eleifend e
rat. Curabitur eu tempus tellus, sed lacinia nunc. Sed aliquam gravida porta. Vivamus eu luctus leo. Vestibulum condimen
tum arcu sem, vitae vehicula ligula ultrices eget. Fusce pretium molestie pellentesque. Nam ultrices mattis sapien ut co
nsectetur. Cras et vehicula felis. Suspendisse quis egestas nunc, id tempor tellus. Proin placerat accumsan tristique.',
owned: 'Sim',
picture: 'fatherhood.svg',
date: ISODate("2022-04-05T18:59:49.801Z"),
reviews: [],
user: ObjectId("624c8dfdd0c88d172dfeebee"),
__v: 0
}
This is my Model
//File Requirements
const mongoose = require('mongoose');
const Review = require('./review');
const Schema = mongoose.Schema;
//Local variables
const sensiblePeriods = ['Movimento', 'Linguagem', 'Detalhes', 'Ordem', 'Desenvolvimento dos Sentidos', 'Refinamento dos Sentidos', 'Graça e Cortesia', 'Música e Ritmo', 'Escrita', 'Leitura', 'Matemática']
//Activity Schema
const ActivitySchema = new Schema({
title: {
type: String,
required: true
},
ages: {
type: String,
required: true
},
sensiblePeriod: {
type: String,
//enum limits the options to those inside the array
enum: sensiblePeriods,
required: true
},
category: {
type: String,
},
theme: {
type: String,
},
description: {
type: String,
required: true,
trim: true
},
owned: {
type: String,
required: true,
default: 'Não'
},
picture: {
type: String,
default: 'fatherhood.svg'
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
date: {
type: Date,
default: Date.now()
//required: true
},
reviews: [
{
type: Schema.Types.ObjectId,
ref: 'Review'
}
]
})
ActivitySchema.post('findOneAndDelete', async function (doc) {
if (doc) {
await Review.deleteMany({
_id: {
$in: doc.reviews
}
})
}
})
//"Compile" Schema
const Activity = mongoose.model('Activity', ActivitySchema);
//Export module to be used elsewhere
module.exports = Activity;
This is the controller taking the information for the route:
module.exports.details = async (req, res, next) => {
const activity = await Activity.findById(req.params.id).populate({
path: 'reviews',
populate: {
path: 'user'
}
}).populate('user');
if (!activity) {
req.flash('error', 'Atividade não encontrada!')
return res.redirect('/atividades')
}
res.render('atividades/detalhes', { activity });
}
And, finally, this is my EJS file:
<%- include('../partials/head') %>
<div class="row mb-3">
<div class="col-md-6">
<div class="card mb-3">
<img src="/public/img/<%=activity.picture%>" alt="" class="card-img-top">
<div class="card-body">
<h3 class="card-title">
<%=activity.title%>
</h3>
<p class="card-text">
<!-- This is the line which renders the text -->
<%=activity.description%>
<!-- ----------------------------- -->
</p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item"><b>Dono: </b>
<%=activity.user.username%>
</li>
<li class="list-group-item"><b>Idades: </b>
<%=activity.ages%>
</li>
<li class="list-group-item"><b>Período Sensível: </b>
<%=activity.sensiblePeriod%>
</li>
<li class="list-group-item"><b>Categoria: </b>
<%=activity.category%>
</li>
<li class="list-group-item"><b>Tema: </b>
<%=activity.theme%>
</li>
</ul>
</div>
<% if(currentUser && activity.user.equals(currentUser._id)) {%>
<div class="card mb-3">
<div class="card-body">
<h4 class="card-text mb-3">Área de Risco</h4>
<a href="/atividades/<%=activity._id%>/editar" class="btn btn-info">Editar Atividade</a>
<form class="d-inline" action="/atividades/<%=activity._id%>/?_method=DELETE" method="POST">
<button class="btn btn-danger">Excluir Atividade</button>
</form>
</div>
</div>
<% } %>
<p><a class="card-link" href="/atividades">Voltar à todas as atividades</a></p>
</div>
<div class="col-md-6">
<!-- <h2 class="text-center card-title mb-2">Comentários</h2> -->
<% if(currentUser) {%>
<div class="card mb-3">
<div class="card-body">
<h4 class="card-title text-center mb-3">Incluir Comentário
</h4>
<form action="/atividades/<%=activity._id%>/reviews" method="POST">
<div class="row mb-3">
<div class="col">
<div>
<label class="form-label" for="title">Título</label>
</div>
<div>
<input class="form-control" type="text" name="review[title]" id="title" size="26">
</div>
</div>
<!-- <div class="col">
<div class="form-outline">
<div>
<label class="form-label" for="date">Data</label>
</div>
<div>
<input class="form-control" type="date" name="review[date]" id="date">
</div> -->
<!-- </div>
</div> -->
</div>
<div class="mb-3">
<div><label class="form-label" for="body">Comentário</label></div>
<div><textarea class="form-control" name="review[body]" id="body" cols="42" rows="5"></textarea>
</div>
</div>
<button class="btn btn-success">Incluir Comentário</button>
</form>
</div>
</div>
<% } %>
<% const reviews=activity.reviews %>
<% for(let review of reviews) { %>
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">
<%= review.title %>
</h5>
<h6 class="card-subtitle">
Autor: <%= review.user.username %>
</h6>
<% const dbDate=review.date.toISOString()%>
<% const day=dbDate.substring(8,10)%>
<% const month=dbDate.substring(5,7)%>
<% const year=dbDate.substring(0,4)%>
<% const lastUpdated=`${day}/${month}/${year}` %>
<p class="text-secondary">
Última Atualização: <%= lastUpdated %>
</p>
<p>
<%= review.body %>
</p>
<% if(currentUser && review.user.equals(currentUser._id)) {%>
<a href="/atividades/<%= activity._id %>/reviews/<%=review._id%>"
class="btn btn-sm btn-info">Editar Comentário</a>
<form class="d-inline"
action="/atividades/<%= activity._id %>/reviews/<%=review._id%>?_method=DELETE "
method="post">
<button class="btn btn-sm btn-danger">Excluir Comentário</button>
</form>
<% } %>
</div>
</div>
<%}%>
</div>
</div>
</div>
<%- include('../partials/foot') %>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
