My Nested {{#each}} does not work.
I am Scraping article titles to my page and I'm using MongoDB/Mongoose. For each article (that I named News) I want user to post comments and view previous comments.
My routes, console.log, and the database itself shows that my api routes are working, but I can't get the comments to display.
My handlebars has the articles rendering to screen, but when GETting the comments it returns a 304.
The Articles display as I intend, it only has a problem with the comments
{{#each News}} is each article
{{#each comment}} is nested inside each News.
{{#each News}}
<div class="panel-block is-active">
<ul>
<li>
<div class="level-left">
<h2 class="subtitle">
<a href="https://www.atptour.com{{this.url}}">
{{this.headline}}
</a>
</h2>
</div>
</li>
<li>
<img width="348" src="https://www.atptour.com{{this.thumbNail}}">
</li>
<li>
<p>{{category}}</p>
</li>
<li>
{{!-- on click remove class .is-hidden on #getComments --}}
<p id="showComments" data-id="{{this._id}}" >Comments</p>
</li>
<li>
{{#each comment}}
<article id="getComments" class="media is-hidden">
<div class="media-content">
<div class="content">
<p>
<small>{{this.time}}</small>
<br />
{{this.body}}
</p>
</div>
</div>
<div class="media-right">
<button class="delete"></button>
</div>
</article>
{{/each}}
{{!-- on click remove class .is-hidden on #postComments --}}
<a id="addComment" >Add Comment</a>
{{!-- TO POST A COMMENT --}}
<article id="postComment" class="media is-hidden">
<div class="media-content">
<div class="field">
<p class="control">
<textarea
class="textarea"
placeholder="Add a comment..."
></textarea>
</p>
</div>
<div class="level">
<div class="level-left">
<div class="level-item">
<a class="button is-info">Submit</a>
</div>
</div>
</div>
</div>
</article>
</li>
</ul>
</div>
{{/each}}
In the {{#each comment}} {{this.time}} and {{this.body}} is blank. But if I simply put {{this}} I get the _id if each comment. The context must be wrong but I don't know why. The comments are properly associated to the News because I can check the get route and it's all there correctly.
Here are the schemas if it helps
new articles
const NewsSchema = new Schema({
headline: {
type: String,
required: true,
},
thumbNail: {
type: String,
required: true,
},
category: {
type: String,
required: true,
},
url: {
type: String,
required: true,
},
// Comments will populate the News
comment: [
{
type: Schema.Types.ObjectId,
ref: "Comment",
},
],
});
const News = mongoose.model("News", NewsSchema);
comments
const CommentSchema = new Schema({
time: {
type: Date,
default: Date.now,
required: true,
},
body: {
type: String,
required: true,
},
});
const Comment = mongoose.model("Comment", CommentSchema);
It wasn't a handlebars problem at all!
It was a route problem.
I was doing this:
app.get("/", function(req, res) {
db.News.find()
.then(News => {
res.render("index", { News });
})
.catch(err => {
console.log(err);
});
});
When I should have been doing this
app.get("/", function(req, res) {
db.News.find()
.populate("comment")
.then(News => {
res.render("index", { News });
})
.catch(err => {
console.log(err);
});
});
I forgot to populate in the res.render. (I was populating the api route, but not this 1!)
Related
Am getting this error when google auth redirects to my secrets page. And also in the secrets page I can't post secrets as they aren't posted in my database. I don't know which elements I have called wrongly.
<%- include('partials/header') %>
<div class="jumbotron text-center">
<div class="container">
<i class="fas fa-key fa-6x"></i>
<h1 class="display-3">You've Discovered My Secret!</h1>
<% usersWithSecrets.forEach(function(foundUsers){ %>
<p class="secret-text"><%=foundUsers.secret%></p>
<% }) %>
<hr>
<a class="btn btn-light btn-lg" href="/logout" role="button">Log Out</a>
<a class="btn btn-dark btn-lg" href="/submit" role="button">Submit a Secret</a>
</div>
</div>
<%- include('partials/footer') %>
app.get("/secrets", function(req,res){
if (req.isAuthenticated()) {
User.find({"secret": {$ne: null}}, function(err, foundUsers){
if(foundUsers){
res.render("secrets", {usersWithSecrets: foundUsers});
}else {
console.log(err);
}
});
app.post("/submit", function(req, res){
const submittedSecret = req.body.secret;
User.findById(req.user.id, function(err, foundUser){
if (err) {
console.log(err);
}else{
if (foundUser) {
foundUser.secret=submittedSecret;
submittedSecret.save(function(){
res.redirect("/secrets");
});
}
}
});
});
The first block of code should catch the user and redirect them to the app.get(secrets)
The second block is a user can post a secret and caught in the database but the page keeps loading infinitely.
I have the following code but it does not post to my Subscriber collection. When I put in an email address it does not post to my subscriber collection type. Also it does not console.log
Using Nuxt3/Strapi4
<template>
<div class="relative flex justify-center w-full h-64 pb-16 mt-14 subscribe-bg">
<Container>
<div class="w-full mx-auto lg:w-3/6">
<div class="px-10 -mt-12 text-center bg-white rounded-lg shadow-xl py-9 subscribe-box">
<Heading tag="h3" font-style="h3">Subscribe</Heading>
<Heading tag="h2" font-style="h2">Never miss a planner</Heading>
<p
class="w-full px-2 mx-auto text-center pb-7 text-brand-grey-400"
>Subscribe to receice the worlds most cutting edge planner news direct to your inbox. Our newsletter is on fire.</p>
<div class="flex items-center">
<form #submit.prevent="handleSuscribe">
<input-field
id="email"
v-model="email.email"
type="email"
name="email"
placeholder="Your email"
class="w-3/4 mr-8"
/>
<Btn class="h-full" type="submit">Subscribe</Btn>
</form>
</div>
</div>
</div>
</Container>
</div>
</template>
<script setup>
import { useToast } from 'vue-toastification';
const toast = useToast();
const email = ref({ email: "" })
const handleSuscribe = async () => {
await $fetch("http://localhost:1337/api/subscribers", {
method: "POST",
body: {
data: {
email: email.value,
}
}
})
console.log(email.value)
console.log(handleSuscribe)
}
</script>
Tried to convert from the following code from Nuxt 2. It looked pretty simple at first but now I am running into issues.
<template>
<div
class="sm:flex mx-auto items-center m-10 justify-center space-x-6 sm:space-x-20 m-3 sm:m-6 mx-6"
>
<div>
<h1 class="text-lg m-7">Sign Up For NewsLetter</h1>
</div>
<div>
<form #submit="handleSuscribe">
<input
id=""
v-model="email"
class="p-2 m-3 sm:m-0 border border-solid border-t-0 border-l-0 border-r-0 border-b-1 outline-none border-black"
type="email"
name=""
placeholder="email"
/>
<button type="submit" class="button--grey">Subscribe</button>
</form>
</div>
</div>
</template>
<script>
export default {
name: 'NewsLetter',
data() {
return {
email: '',
}
},
methods: {
async handleSuscribe(e) {
e.preventDefault()
this.$swal({
title: 'Successful!',
text: 'Thanks for Subscribing',
icon: 'success',
button: 'Ok',
})
await this.$strapi.$subscribers.create({ Email: this.email })
this.email = '' // clear email input
},
},
}
</script>
I have this issue that every time the div is loaded using div.load in the ajax success, the code for sortable will not work. Sortable will work again after the page is refreshed manually. What could be the possible solution for this?
$(document).on('click', '#add-song-tag', function() {
tag_id = $('#tags').val();
$.ajax({
url: base_url + '/songtags/add_song_tag',
type: 'POST',
data: {
song_info_id: song_info_id,
tag_id: tag_id
},
success: function() {
$('#category').load(window.location.href + ' #category');
$('#modal-categories').trigger('change');
},
error: function(xhr) {
console.log(xhr.responseText);
}
})
});
I have my code in the sortable.js like
$( function() {
$( "#sortable, #sortable1" ).sortable({
connectWith: ".draggable-group",
start: function(event, ui){
$(ui.item).width($('#sortable div').width());
}
// containment: "parent",
// tolerance: "pointer"
}).disableSelection();
} );
and in the html it looks something like:
<?php if($selected_tag_for_m['category_id'] == $tempo_id):?>
<div class="btn-group draggable-group">
<div>
<i class="fa fa-minus-circle fa-lg delete-a-tag" aria-hidden="true"></i>
</div>
<div type="button" class="btn btn-default btn-color"><i class="fa fa-circle-o custom-text-blue"></i> <?php echo $selected_tag_for_m['tag_name'];?> </div>
<div type="button" class="btn btn-default custom-bgcolor-blue dropdown-toggle" data-toggle="dropdown">
<span><i class="fa fa-pencil"></i></span>
<span class="sr-only">Toggle Dropdown</span>
</div>
<ul class="dropdown-menu" role="menu" id="tempo">
<?php foreach($tempos as $tempo):?>
<li data-id="<?php echo $selected_tag_for_m['info_tag_id']?>"><a href="" data-id="<?php echo $tempo['tag_id']?>" class="songtaglist" ><?php echo $tempo['tag_name'];?></a></li>
<?php endforeach;?>
</ul>
</div>
<?php endif;?>
I found solution to this by calling sortable.js script in body of the load function. The code looks like this:
$('#category').load(window.location.href + ' #category', function(){
$.getScript(base_url + '/assets/js/sortable.js');
});
I am using form component to insert data into the Mongo-Collection. When I check in terminal for stored information I do successfuly store Title and data from Select input, but have value of null for both url and file inputs.
Here is the code for handling insert method on import folder:
Meteor.methods({
'posts.insert' : function(post) {
return Posts.insert({
createdAt: new Date(),
title: post.title,
social: post.social,
link: this.link,
file: this.file
});
}
});
Here is the component code for handling form submit:
import React, { Component } from 'react';
class AddPost extends Component {
constructor(props) {
super(props);
this.state = {error: ''};
}
handleSubmit(event) {
event.preventDefault();
const title = this.refs.title.value;
const social = this.refs.social.value;
const link = this.refs.link.value;
const file = this.refs.file.value;
Meteor.call('posts.insert', {title, social, link, file});
}
render() {
return (
<div className="modal fade" id="myModal" tabIndex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div className="form-outer">
<form id='add_post' onSubmit={this.handleSubmit.bind(this)}>
<div className='form-text form-header'>
<p><strong>Hey</strong>, master<span className='error'>{this.state.error}</span></p>
<p>Lets share something new today?</p>
</div>
<input ref="title" type="text" className="form-input" placeholder="What about the title?" />
<div className='form-text form-header form-header-distance'>
<p>Where should I point the way?</p>
</div>
<select ref="social" className="form-select">
<option>Select</option>
<option>Instagram</option>
<option>Twitter</option>
</select>
<input ref="link" type="url" className="form-input" placeholder="Point the way" />
<div className='form-text form-header form-header-distance'>
<p>And what about the image?</p>
</div>
<label className="file form-file">
<input ref='file' className='form-input' type="file" id="file" />
<span className="file-custom"></span>
</label>
<button type="button" className="form-button" data-dismiss="modal">Close</button>
<button type="sumbit" className="form-button" >Save</button>
</form>
</div>
</div>
);
}
}
export default AddPost;
P.S: It's out of topic of these question, but I will do appreciate a lot if you could point me to some external resource or explain if it's possible to upload/store new images (not static from public folder) from local machine and serve them to front-end view?
Make your meteor method as below:
Meteor.methods({
'posts.insert'(post){
post.createdAt: new Date();
Posts.insert(post);
}
})
I am using mizzao/meteor-autocomplete and am having problems in trying to get it to work.
When viewing the page in my browser, I am getting no results at all when typing any text. I've created the appropriate collection:
Institutions = new Mongo.Collection("institutions");
and know that there is data in the actual db, however still no success.
I've included my files below.
publications.js (located in the server folder)
Meteor.publish('institutions', function(args) {
return Institutions.find({}, args);
});
registrationStart.js
I've two helpers; one that actually powers the search and the other that should be returning the institutions. I have also tried this with the token: '#' argument with no success.
if (Meteor.isClient) {
Template.registrationStart.helpers({
settings: function() {
return {
position: "top",
limit: 7,
rules: [{
collection: Institutions,
field: "name",
options: '',
matchAll: true,
template: Template.institutionSelectDisplay
}]
};
},
institutions: function() {
return Instititions.find();
}
});
Template.registrationStart.events({
"autocompleteselect input": function(event, template, doc) {
// Session.set(event.target.name, event.target.value);
console.log("selected: ", doc);
console.log("event.target.name: ", event.target.name);
console.log("event.target.value: ", event.target.value);
}
});
}
registrationStart.html template
<template name="registrationStart">
<div class="panel-body" id="loginForm">
<h2 class="pageTitle">veClient Registration</h2>
<form>
<div> </div>
<fieldset>
{{> inputAutocomplete settings=settings id="institution" class="input-xlarge" placeholder="type institution here"}}
</fieldset>
<div> </div>
<button type="submit" class="btn btn-primary btn-sm">Continue Registration</button>
</form>
</div>
</template>
And the template to be rendered
<template name="institutionSelectDisplay">
<p class="inst-state">{{city}}, {{state}}</p>
<p class="inst-name">{{name}}</p>
<p class="inst-description">{{email}}</p>
</template>
Problem resulted because there was no subscription to the "institutions" publication. So need to add a subscribe statement to the registrationStart.js file:
Meteor.subscribe('institutions');