En el helper del conteo, pudiéramos validar si el arreglo de respuestas viene en null para devolver 0, y así no tendríamos que incluir el tag #if en la plantilla.
Introducción
Qué necesitas para este curso y qué aprenderás sobre Node.js con Hapi
Conceptos principales de hapi y creación de nuestro primer servidor
Breve historia y estado actual
Creando un sitio básico con Hapi
El objeto h, response y sus herramientas
Uso de plugins - Contenido estático
Plantillas con Handlebars
Renderizado de vistas - Layout y template del home
Recibiendo parámetros en una ruta POST - Creación del registro
Definir una mejor estructura con buenas prácticas en Hapi
Validando la información - Implementando Joi
Introducción a Firebase
Creando un modelo y guardando en firebase
Implementando el login y validación del usuario
Autenticación de usuarios - Cookies y estado
Manejando errores
Visualización de errores
Controlar el error 404 en inert y el error de validación
Repaso - Creación del modelo y controlador para preguntas
Repaso - Creación de las rutas para crear preguntas
Listar las últimas preguntas en el home
Aplicacion de conceptos avanzados
Enrutamiento avanzado - visualizando una pregunta
Enrutamiento avanzado - respondiendo una pregunta
Generando la lógica de la plantilla según si es creador o contribuidor
Métodos de servidor - respuesta correcta
Usando métodos de servidor
Manejo del caché - Agregando el home al caché
Procesamiento de archivos - Aceptando imágenes
Logging con Good - Monitoreando el servidor
Creación de plugins - Teoría
Creación de plugins - Implementando un API REST
Estrategías de autenticación - Asegurando el API REST
Seguridad básica - Asegurando el servidor contra CSRF
Seguridad básica - Asegurando el servidor contra XSS
Herramientas de desarrollo
Depuración del proyecto
Ecosistema de Hapi
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Última oportunidad para asegurar tu aprendizaje por 1 año a precio especial
Antes: $249
Paga en 4 cuotas sin intereses
Termina en:
Para crear la funcionalidad de respuesta, creamos un método nuevo en el modelo de preguntas llamado answer
. Este método nos permitirá insertar con push el objeto con la respuesta individual para una pregunta que será almacenada en un arreglo child llamado answers.
Luego definimos el método respectivo en el controlador de las preguntas y creamos la ruta que manejará el envío de las respuestas desde el formulario.
Es importante tener en cuenta que el ID de la pregunta que estamos respondiendo, corresponde a un input de tipo hidden en la vista, por lo que debemos asignar apropiadamente su valor a partir del key recibido en la ruta.
Finalmente, actualizamos la vista de detalles de pregunta, recordando que las respuestas son un arreglo en la base de datos de Firebase, por lo que deberemos recorrerlo igualmente con la instrucción {#each ... } ... {/each}
de handlebars.
Para el conteo de las respuestas crearemos un helper personalizado de handlebars y lo registraremos en el index.js
con el método .registerHelper( ‘<nombre helper>’, <función helper> ). Los helpers son funciones de JavaScript que están disponibles globalmente en la aplicación para ser incluídas en cualquiera de las vistas.
Aportes 12
Preguntas 0
En el helper del conteo, pudiéramos validar si el arreglo de respuestas viene en null para devolver 0, y así no tendríamos que incluir el tag #if en la plantilla.
no sería mejor crear un modelo para “answer” ?
Para evitar el if dentro del archivo index.hbs podemos poner el siguiente código en el index.js
handlerbars.registerHelper('answerNumber', (answers) => {
if (!answers) return 0;
const keys = Object.keys(answers).length;
return keys;
});
en el archivo index.hbs solo agregamos esto
{{answerNumber question.answers}}
✌
😊✌
A la funcion answerQuestion agregué un if() que evalúa si el usuario está o no está logueado. Si no lo esta, lo redirecciona al login.
async function answerQuestion (req, h) {
if (!req.state.user) {
return h.redirect('/login')
}
let result
try {
result = await questions.answer(req.payload, req.state.user)
console.log('Respuesta creada' + result);
} catch (error) {
console.error(error);
}
return h.redirect('/question/' + req.payload.id)
}```
Me sigue gustando más como se ve con pug…
El punto es que pug acepta bloques de código dentro de la vista
extends ./layout/layout
block content
main.container-fluid(role="main")
.jumbotron.bg-white
.container
h1.display-3 FAQ
p
| The best place to learn and for those who are learning, ask a question
| to clarify your doubts and share your knowledge if you know the answer
.container
h2.mb-4 Last Questions
if questions
each q, key in questions
.card.bg-white.mb-3
.card-body
.row
.col-2.text-center
a.text-dark(href="#")
-
let numAns = 0;
if(q.answers){
numAns = Object.keys(q.answers).length
}
h3=numAns
| Answers
.col-10.d-flex.align-items-stretch
h4.mt-3
a.text-dark(href="/question/"+key)= q.title
hr
else
.card.bg-white.mb-3
.card-body
.row
.col-2.text-center
h3
.col-10.d-flex.align-items-stretch
h4.mt-3= error
block footer
include ./partials/footer
block scripts
include ./partials/scripts
controller.question.js
'use strict'
const questions = require('../models/index').questions
async function createQuestion(req, h) {
let result
try {
result = await questions.create(req.payload, req.state.user)
console.log(`Pregunta creada con el ID: ${result}`)
return h.response(`Pregunta creada con el ID: ${result}`)
} catch (error) {
console.error(`Ocurrio un error: ${error}`)
return h.view('ask', {
title: 'Crear pregunta',
error: 'Problemas creado la pregunta'
}).code(500).takeover()
}
}
async function answerQuestion(req, h) {
let result
try {
result = questions.answer(req.payload, req.state.user)
console.log(`Respuesta creada: ${result}`)
} catch (error) {
console.error(error)
}
return h.redirect(`/question/${req.payload.id}`)
}
module.exports = {
createQuestion: createQuestion,
answerQuestion: answerQuestion
}
models.questions.js
'use strict'
class Quiestions {
constructor(db) {
this.db = db
this.ref = this.db.ref('/')
this.collection = this.ref.child('questions')
}
async create (data, user) {
const ask = {
...data
}
ask.owner = user
const question = this.collection.push()
question.set(ask)
return question.key
}
async getLast(amount) {
const query = await this.collection.limitToLast(amount).once('value')
const data = query.val()
return data
}
async getOne (id) {
const query = await this.collection.child(id).once('value')
const data = query.val()
return data
}
async answer (data, user) {
const answers = await this.collection.child(data.id).child('answers').push()
answers.set({
text: data.answer,
user: user
})
return answers
}
}
module.exports = Quiestions
no es malo tener el id en el input vacio , ya que se puede ver en inspeccionar > elementos ?, o si hay ?
Modifique un poco el código y quedo así:
index.js
handlebars.registerHelper('answerNumber', (answers) => {
if (answers === undefined) {
return 0;
}
const keys = Object.keys(answers);
return keys.length;
});
index.hbs
<h3>
{{answerNumber question.answers}}
</h3>
me agrado la funcion que tiene handlerbars, me gustaria aplicar esa parte con express js
En el modelo de questions, en la funcion getOne, pueden modificar data.answers para que quede ordenado, siguiendo el ejemplo de un compañero de la clase anterior quedaría así.
async getOne(id){
const query = await this.collection.child(id).once('value');
const data = query.val();
const orderedAnswers = {};
Object.keys(data.answers).reverse().map(key => orderedAnswers[key] = data.answers[key]);
return {
...data,
answers: orderedAnswers,
};
}```
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?
o inicia sesión.