Post not showing all content in Vue.js app - node.js

I'm building my first Vue app, most of it works fine, but when I click in a post to open the selected post, it doesn't show properly ( Image, title and content don't show ) in the post page, it show the card with the buttons but not the other content, everything shows in home page.
I hope some kind soul can show me some light...
P.S. I'm a beginner so simple terms would be appreciated.
This is my Home page.
<template>
<v-container>
<v-alert border="left" close-text="Close Alert" color="green accent-4" dark dismissible v-if="this.$route.params.message">
{{ this.$route.params.message }}
</v-alert>
<v-row no-gutters>
<v-col sm="4" class="pa-3" v-for="post in posts" :key="post._id">
<v-card class="pa-1" :to="{ name: 'post', params: { id: post._id } }">
<v-img height="250" :src="`/${post.image}`"></v-img>
<v-btn class="ml-4 mt-3" small outlined color="indigo">
{{ post.category }}
</v-btn>
<v-card-title class="headline">
{{ post.title }}
</v-card-title>
<v-card-text class="py-0">
{{ post.content.substring(0, 100) + '...' }}
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
import API from '../api'
export default {
name: 'Home',
data() {
return {
posts: [],
};
},
async created() {
this.posts = await API.getAllPost();
}
};
</script>
and this is my post page
<template>
<v-container>
<v-row no-gutters>
<v-col sm="10" class="pa-4 mx-auto">
<v-card class="pa-2">
<v-img :src="`${ post.image }`"></v-img>
<v-card-actions class="pb-0">
<v-row class="mt-1 mx-1">
<v-col sm="2">
<v-btn small outlined color="primary">{{ post.category }}</v-btn>
</v-col>
<v-col sm="10" class="d-flex justify-end">
<v-btn color="success" text :to="{ name: 'edit-post', params: { id: post._id } }">Edit</v-btn>
<v-btn color="red" text #click="deletePost(post._id)">Delete</v-btn>
</v-col>
</v-row>
</v-card-actions>
<v-card-subtitle class="headline">
<h3>{{ post.title }}</h3>
</v-card-subtitle>
<v-card-text class="grey--text">
<p>{{ post.content }}</p>
<p>{{ post.created }}</p>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
import API from '../api';
export default {
data() {
return {
post: {},
};
},
async created(){
const response = await API.getPostByID(this.$route.params.id);
this.post = response;
},
methods: {
async deletePost(id) {
const response = await API.deletePost(id);
this.$router.push({ name: 'Home', params: { message: response.message } });
},
},
}
</script>

Related

How to set active tab dynamically in ejs templates of nodejs express app?

This is my header template, which will load to every page.
<!-- ======= Header ======= -->
<header id="header" class="d-flex align-items-center">
<div class="container d-flex align-items-center justify-content-between">
<h1 class="logo"><%= title %><span>.</span></h1>
<!-- Uncomment below if you prefer to use an image logo -->
<!-- <img src="/assets/img/logo.png" alt="">-->
<nav id="navbar" class="navbar">
<ul>
<%
const menu = [
{
name: 'Home',
url: '/'
},
{
name: 'About',
url: '/about'
},
{
name: 'Services',
url: '/services'
},
{
name: 'Portfolio',
url: '/portfolio'
},
{
name: 'Team',
url: '/team'
},
{
name: 'RatesCalculator',
url: '/ratesCalculator'
},
{
name: 'Contact',
url: '/contact'
}
]
for ( let i in menu ) { %>
<% if ( menu[i].name.toLowerCase() == activestate.toLowerCase() ) { %>
<li><a class="nav-link scrollto active" href="<%= menu[i].url %>" ><%= menu[i].name %></a></li>
<% } else { %>
<li><a class="nav-link scrollto" href="<%= menu[i].url %>" ><%= menu[i].name %></a></li>
<% } %>
<% } %>
</ul>
<i class="bi bi-list mobile-nav-toggle"></i>
</nav><!-- .navbar -->
</div>
</header><!-- End Header -->
To set it dynamically, the active tab, I am using the logic below in template and the middleware in index.js.
app.use(function(req, res, next){
console.log(req)
res.locals.title = "Marker";//To set website title
req.active = req.path.split('/')[1] // [0] will be empty since routes start with '/'
if (req.length === 0) req.active = "Home"
next();
});
It is working but I feel it is bit complicated and repetitive code is there.
Can you please suggest a better approach.

How to display json data using react jsx with sweet alert 2?

I am developing a script in react and nodejs. The idea is about displaying the content from json to the react page using sweet alert 2.
The output does not shows results which is suppose to display the content from the json file.
Here are my codes
import React from 'react';
import Swal from 'sweetalert2';
import withReactContent from 'sweetalert2-react-content';
const MySwal = withReactContent(Swal);
const json = require('json-loader!./myfilepath.json');
class pageJSONOCR extends React.Component
{
getData = () =>
{
console.log("Button Clicked");
MySwal.fire({
title: 'Success!',
text: "Button is clicked",
type: 'success',
showCancelButton: false,
confirmButtonText: 'View File'
}).then((result) => {
if (result.value) {
MySwal.fire(
'The Content Of Json File',
`${json}`
)
}
})
}
render()
{
console.log("Header - Rendered");
return(
<div className="container">
<div className="py-5 text-center">
<div className="jumbotron">
<div className="container">
<h1>Out Put</h1>
<hr/>
<p className="lead">Check The JSON File</p>
<button className="btn btn-primary" value="Submit" onClick={this.getData}>Submit</button>
</div>
</div>
</div>
</div>
);
}
}
export default pageJSONOCR;
If there is any solutions do help me.
Thanks in advance!
use sweetalert2-react-content
import withReactContent from 'sweetalert2-react-content';
import Swal from 'sweetalert2';
const basic = withReactContent(Swal.mixin({
title: 'Success',
text: 'text here.',
confirmButtonText: "Okay.",
showCloseButton: true,
showCancelButton: true,
cancelButtonText: 'Cancel'
}));
...
<div>
{
basic.mixin({
title: <i>title</i>
}).fire()
}
</div>

Displaying a detailed post from ngFor

I'm creating a Blog using Angular 7, MongoDB and NodeJS. So far I have created a component that loops through all the posts from the database and displays them on a single page.
<div class="container-fluid">
<div class="row" *ngIf="posts.length > 0" >
<div class="col-lg-12 col-md-12 col-xl-12 text-center" *ngFor="let post of posts ">
<div class="post-preview" >
<h2 class="post-title text-center">
{{ post.title }}
</h2>
<h3 class="post-subtitle text-center">
{{ post.subtitle }}
</h3>
<br>
<div class="post-image">
<img [src]="post.imagePath" [alt]="post.title">
</div>
<br>
<p class="post-meta text-center">{{post.date}}</p>
</div>
</div>
</div>
</div>
This is for displaying all the blog posts on a single page. When a user clicks on a single post he should be directed to a page that shows detailed information for that post only (like the blog content). How do I implement that?
In the posts.service I have the following function for getting a single post.
getPost(id: string) {
return this.http.get<{_id: string, title: string, subtitle: string, content: string, date: Date, imagePath: string}>(
'http://localhost:3000/api/posts/' + id);
}
And on the backend I have the following route:
router.get("/:id", (req, res, next) => {
Post.findById(req.params.id).then(post => {
if (post) {
res.status(200).json(post);
} else {
res.status(404).json({
message: 'Post not found!'
});
}
});
});
I found the answer here: https://codecraft.tv/courses/angular/routing/parameterised-routes/
The soloution:
[1]
Spefify the parameterised route in router as:
{ path: 'blog/:postId', component: SinglePostComponent }
[2]
Create a link to direct the user to the the specified blog post
<a [routerLink]="['/blog', post.id]" > </a>
[3]
In the SinglePostComponent.ts put the following code:
export class SinglePostComponent implements OnInit {
post: Post;
private postId: string;
constructor(
private route: ActivatedRoute,
private postsService: PostsService
) {}
ngOnInit() {
this.route.paramMap.subscribe((paramMap: ParamMap) => {
this.postId = paramMap.get('postId');
this.postsService.getPost(this.postId).subscribe(postData => {
this.post = {id: postData._id, title: postData.title, subtitle: postData.subtitle,
content: postData.content, date: postData.date, imagePath: postData.imagePath};
});
}
);
}
}

How to pass 2 values in .render() to Handelbars

I am trying to pass multiple values into res.render to be passed into my handlebars template. It seems to fulfil the condition but it doesn't show the content.
I'm trying to show a special navbar and a users snippets (their data) if they're logged in. Otherwise I want to display my normal navbar and all snippets (data from all users).
I've got it working if I just hand in a single value, but I can't seem to hand in multiple values.
Express code:
router.route('/')
.get(function (request, response) {
if (request.session.name) {
Snippet.find({ user: request.session.name._id }, function (err, data) {
if (err) {
console.log(err)
}
data.forEach(function (element, err) {
if (err) {
console.log(err)
}
})
let context = {
snippets: data.map(function (snippet) {
return {
_id: snippet._id,
user: snippet.user,
title: snippet.title,
body: snippet.body,
createdAt: snippet.createdAt
}
})
}
response.render('home/index', {loggedIn: true, context: context}) //Here is the issue
})
}
Handlebars template:
<ul class="people_list">
{{#if loggedIn}}
{{!-- Logged in --}}
{{#each snippets}}
<h2><i class="star fa fa-star-o" aria-hidden="true"></i> {{title}}</h2>
<h4>{{ createdAt }}</h4>
<pre>
<code class="language-javascript">{{body}}</code>
</pre>
<hr />
{{/each}}
{{else}}
{{!-- Not logged in --}}
{{#each snippets}}
<h2><i class="star fa fa-star-o" aria-hidden="true"></i> {{title}}</h2>
<h4>{{ createdAt }}</h4>
<pre>
<code class="language-javascript">{{body}}</code>
</pre>
<hr />
{{/each}}
{{/if}}
</ul>
You're passing in an array called context but referring to it as snippets in the handlebars code.
Either change your handlebars template to called {{#each context}} or change your nodejs code to response.render('home/index', {loggedIn: true, snippets: context}).

Editing text on a page in node js

I am trying to implement a simple edit feature in my app. In my profile.handlebars file, I have an edit button. When clicked, I'd like the user's information to appear in the text input fields on the form in order to allow the user to edit their existing information.
Right now, they would have to input all of their information over again (and every field in the form would need to be filled out due to validation that I have implemented), click Submit, and their profile can be updated. Is this possible without using a framework (like Angular)? For example, in LinkedIn, a user can hover over a section of their profile causing the edit buttons to highlight, then click a single edit button, and they're instantly in editing mode. That might be too advanced for my purposes right now, but eventually, I'd love to have functionality like that.
I have a post request in my routes file to handle a user posting information to their profile:
router.post('/add', function(req, res) {
req.checkBody({
'city': {
errorMessage: 'Please enter your city'
},
'state': {
errorMessage: 'Please enter your state',
notEmpty: true
},
'zip': {
errorMessage: 'Please enter your zip code',
notEmpty: true
},
'about': {
errorMessage: 'Please briefly describe yourself',
notEmpty: true
}
});
console.log("req.user " + req.user);
var errors = req.validationErrors();
if (errors) {
res.render('profile', {
errors: errors
});
} else {
var user_info = new User_Info({
city: req.body.city,
state: req.body.state,
zip: req.body.zip,
about: req.body.about,
user_name: req.user.username
});
user_info.save(function(err, user_info) {
if (err) throw err;
});
res.redirect('profile/' + req.user.username)
}
})
Then, I have my profile.handlebars file:
{{#if errors}}
Uh oh! Something went wrong. Please review the below errors, and try again.<br><br>
<ul>
{{# each errors }}
<li style="color: red">{{this.msg}}</li>
{{/each}}
</ul>
{{else}}
<h3 align="center">Profile ({{user_name.name}})</h3>
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="thumbnail" style="border-radius: 12px">
<div class="caption">
<p>City: {{# each information }} {{this.city}} {{/each}}</p>
<p>State: {{# each information }} {{this.state}} {{/each}}</p>
<p>Zip: {{# each information }} {{this.zip}} {{/each}}</p>
<p>About: {{# each information }} {{this.about}} {{/each}}</p>
<div class="btn-group">
<button type="Edit" class="btn btn-danger dropdown-toggle deleteLocation" data-id="{{this.id}}">Edit</button>
</div>
</div>
</div>
</div>
</div>
<br>
<center>
<form method="POST" action="/users/add">
<input type="text" name="city" placeholder="City" style="text-align: left">
<br><br>
<input type="text" name="state" placeholder="State" style="text-align: left">
<br><br>
<input type="text" name="zip" placeholder="Zip" style="text-align: left">
<br><br>
<textarea name="about" placeholder="About You" style="text-align: left; resize: both;" rows="5" cols="50"></textarea>
<br><br>
<div class="btn-group">
<button type="submit" class="btn btn-success dropdown-toggle" aria-haspopup="true" aria-expanded="false">Submit</button>
</div>
<br><br>
</form>
</center>
{{/if}}
Please let me know if you need additional info to help me solve this issue. Thanks!
you can use this code for node for editing the parameters , city,state,zip and about.
router.post('/add', function (req, res) {
var users = req.Collection;
var city = req.body.city;
var state = req.body.state;
var zip = req.body.zip;
var about = req.body.about;
var user_id = req.body.user_id;
if (city && state && ) {
users.findOneAndUpdate({_id: user_id}, {$set: {city: city, state: state, zip: zip, about:about}}, function (err, user) {
if (err) {
res.json({status: 0, message: err});
}
if (!user) {
res.json({status: 0, msg: "not found"});
} else {
res.json({status: 1, city: city, state: state, zip: zip, about:about, message: " edit success"});
}
})
} else {
res.json({status: 0, msg: "Invalid Fields"});
}
});

Resources