How to change routes dynamically for each component in VueRouter? - vue.js

I am trying to have dynamic routes in my application.
I have main route '/blogs' which contains 3 static blogs, I want is that each blog should be rendered with its own content like '/blogs/blog-1' and for blog 2 like '/blogs/blog-2', I have tried with docs but couldn't understand as I am beginner.
Here is my code to all the components,
router.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from './components/views/Home.vue'
import Blogs from './components/views/Blogs.vue'
import Blog_1 from './components/blogs/Blog_1';
import Blog_2 from './components/blogs/Blog_2';
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/",
component: Home,
},
{
path: "/blogs",
component: Blogs,
children: [
{
path: 'blog-1',
component: Blog_1
},
{
path: 'blog-2',
component: Blog_2
}
]
},
],
scrollBehavior(to,) {
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth',
top: 0
}
}
},
});
export default router;
Here is Blog.vue which have all the static blogs not full but half
<template>
<!-- ***** Blog Start ***** -->
<section class="section" id="blog">
<div class="container">
<!-- ***** Section Title Start ***** -->
<div class="row">
<div class="col-lg-12">
<div class="center-heading">
<h2 class="section-title">Blog Entries</h2>
</div>
</div>
<div class="offset-lg-3 col-lg-6">
<div class="center-text">
<p>
Integer molestie aliquam gravida. Nullam nec arcu finibus,
imperdiet nulla vitae, placerat nibh. Cras maximus venenatis
molestie.
</p>
</div>
</div>
</div>
<!-- ***** Section Title End ***** -->
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12">
<div class="blog-post-thumb">
<div class="img">
<img src="assets/images/1x/blog-item-01.png" alt="" />
</div>
<div class="blog-content">
<h3>
Online Presence of Business
</h3>
<div class="text">
As Covid-19 came, it throttled small and medium businesses in
great depth. Not every one can recover from it.
</div>
Read More
</div>
</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12">
<div class="blog-post-thumb">
<div class="img">
<img
height="220"
width="370"
src="assets/images/1x/blog-item-02.jpg"
alt=""
/>
</div>
<div class="blog-content">
<h3>
<a href="#"
>Why Having a Website is Important for a small business?</a
>
</h3>
<div class="text">
The number of small businesses with a website is surprisingly
low despite the growth in technology.
</div>
Read More
</div>
</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12">
<div class="blog-post-thumb">
<div class="img">
<img
height="220"
width="370"
src="assets/images/1x/blog-item-03.jpg"
alt=""
/>
</div>
<div class="blog-content">
<h3>
Impact of Advertisment on Customer
</h3>
<div class="text">
Have you ever thought, why giant companies such as apple,
google, Samsung invest millions on advertisement?
</div>
Read More
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ***** Blog End ***** -->
</template>
As I want to click on read more ,so it should go to the complete article which should be in another component.
Thank You

You can use route params to match those slugs:
routes: [
{
path: "/",
component: Home,
},
{
path: "/blogs/:slug", // This `:` syntax means it's a variable
name: 'blogs',
component: Blogs
},
],
(You don't need the child routes you had.) When you use a route param like that, the :slug segment can be replaced by whatever you like. So if you do visit a route like /blogs/blog-1, it will match that route. And the dynamic portion will be available in the component as
this.$route.params.slug
In this example, that would show "blog-1". Also, notice that I gave the route a name "blogs". That's so that when you want to visit that route, you can use a <router-link> like:
<router-link :to="{ name: 'blogs', params: { slug: 'blog-1' }}">
Blog 1
</router-link>

Related

How can I preserve data between switching between tabs in Vue?

I'm trying to learn some Vue, I have tab component it has 2 tabs with some dropdowns and text fields inside, the problem is when I switch between tabs it loss data like selected items from dropdowns or text values, I've tried with v-model but nothing, any help?
Here is the tab view
<script setup>
import { ref } from 'vue';
const nestedRouteItems = ref([
{
label: 'Personal',
to: '/uikit/ficha'
},
{
label: 'Seat',
to: '/uikit/ficha/seat'
},
]);
</script>
<template>
<div class="grid">
<div class="col-12 md:col-12">
<div class="card p-fluid">
<h5>Ficha</h5>
<div class="col-12 md:col-12">
<div class="card card-w-title">
<h5>Tab container</h5>
<p>Lorem ipsum dolor sit amet, consectetur.</p>
<TabMenu :model="nestedRouteItems" />
<router-view />
</div>
</div>
</div>
</div>
</div>
</template>
Here is the content of first tab:
<template>
<div class="flex align-items-center py-5 px-3">
<div class="card p-fluid" style="width:800px">
<h5>Datos personales</h5>
<div class="field">
<label for="name1">Nombre</label>
<InputText id="name1" type="text" />
</div>
</div>
</div>
</template>
Here is the content of second tab:
<script setup>
import { ref } from 'vue';
const dropdownItems = ref([
{ name: 'Principal', code: 'Principal' },
{ name: 'Laboral', code: 'Laboral' },
{ name: 'Familiar', code: 'Familiar' }
]);
const dropdownItem = ref(null);
</script>
<template>
<div class="flex align-items-center py-5 px-3">
<div class="card p-fluid" style="width:800px">
<h5>Domicilio</h5>
<div class="field">
<label for="tipoDomicilio">Tipo de domicilio</label>
<Dropdown id="tipoDomicilio" v-model="dropdownItem" :options="dropdownItems" optionLabel="name" placeholder="Elegir opciĆ³n..."></Dropdown>
</div>
</div>
</div>
</template>
You can use KeepAlive to do this.
<KeepAlive> is a built-in component that allows us to conditionally
cache component instances when dynamically switching between multiple
components.
If your tab components are dynamic then use KeepAlive like this-
<KeepAlive>
<component :is="tabComponent" />
</KeepAlive>
If you are using tab components individually then do like this-
<KeepAlive>
<tab-a></tab-a>
<tab-b></tab-b>
</KeepAlive>
You can read more about KeepAlive in the documentation.

How to fix nuxt auth page reload problem?

When I log in with nuxt auth, I redirect the user to his profile page. But after reload on the profile page I get an error like the screenshot:
I have searched this problem related to #nuxtjs/auth-next ssr problem. Most of the solution is to downgrade the #nuxtjs/axios version. I have already tried this but not fixed.
Here is my profile page code:
<template>
<div v-show="$auth.user">
<!-- profile image -->
<div class="w-full flex">
<div>
<div class="bg-gray-200 p-5 w-40 h-44"></div>
</div>
<div class="ml-6">
<h2 class="font-bold text-2xl mb-4">Profile Details</h2>
<h6 class="font-semibold text-lg">{{$auth.user.name}}</h6>
<p><span class="font-medium">Email: </span>{{$auth.user.email}}</p>
<p><span class="font-medium">Phone: </span>{{$auth.user.phone}}</p>
<p><span class="font-medium">Last Login: </span>{{$auth.user.lastLoginForHuman}}</p>
<nuxt-link to="/customer/change-password" class="block mt-3 text-primary-500 text-sm hover:underline">Change Password</nuxt-link>
</div>
</div>
<!-- details -->
<div class="w-full mt-5">
<div class="grid grid-cols-2 sm:grid-cols-2 gap-4">
<input-field label="First name"></input-field>
<input-field label="Last name"></input-field>
<input-field type="email" label="Email"></input-field>
<input-field label="Phone"></input-field>
</div>
<div class="flex justify-end">
<button-field label="Update" class="bg-primary-500 text-white py-3 px-10"></button-field>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Profile",
data() {
return {
form: {
firstName: this.$auth.user?.firstName,
lastName: this.$auth.user?.lastName,
email: this.$auth.user?.email,
phone: this.$auth.user?.phone,
},
photo: null,
};
},
};
</script>
"#nuxtjs/auth-next": "^5.0.0-1624817847.21691f1",
"#nuxtjs/axios": "^5.13.6",
"nuxt": "^2.15.7"

Vue App Not Displaying reactor-link pieces

I'm trying to work through a tutorial that uses Vue and have gotten stuck. I'm not sure why my buttons are not showing appropriately. Where am I messing up? Thanks in advance for your help.
From the images:
Expected Outcome: Buttons at top right
Actual Result: Buttons at top right are missing
App.vue:
<template>
<div id="wrapper">
<nav class="navbar is-dark">
<div class="navbar-brand">
<router-link to="/" class="navbar-item"><strong>Djackets</strong></router-link>
<a class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbar-menu">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu" id="navbar-menu">
<div class="navbar-end">
<router-link to="/summer" class="navbar-item">Summer</router-link>
<router-link to="/winter" class="navbar-item">Winter</router-link>
<div class="navbar-item">
<div class="buttons">
<router-link to="/log-in" class="button is-light">Log In</router-link>
<router-link to="/cart" class="button is-success">
<span class="icon"><i class="fas fa-shopping-cart"></i></span>
<span>Cart</span>
</router-link>
</div>
</div>
</div>
</div>
</nav>
<section class="section">
<router-view/>
</section>
<footer class="footer">
<p class="has-text-centered">Copyright (c) 2021</p>
</footer>
</div>
</template>
<style lang="scss">
#import '../node_modules/bulma';
</style>
index.html:
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
Expected Vue: Missing icons on top right
Actual Result: Missing icons on top right
Okay, so the code is all correct, the issue has to do with sizing. The device display is small and activated the mobile version which is not configured yet.
Upon using a larger screen, or adjusting the zoom if you can not use a larger screen, the buttons appear as they should.

router link in v-if is working but url does not change

i have succeed create router link in v-if but the url is does not change, what is expected is url change so if user click "go back one page" it is goes to previews page
<template>
<div class="container-fluid">
<div class="row" v-if="productAllData">
<div v-for="item in productAll" :key="item._id" class="col-md-2 col-xs-6">
<div class="card card-margin-right card-buttom" #click="clickProductById(item._id)">
<img v-bind:src="item.image[0].filename" />
<div class="card-body">
<h5 class="card-title">{{item.name}}</h5>
<p>
{{item.description}}<br>
<span class="font-weight-bold">{{item.fprice}} / {{item.unit}}<br></span>
stock : {{item.quantity}}<br>
</p>
</div>
</div>
</div>
</div>
<product-by-id :id="id" :test="`/productall/${id}`" v-if="productByIdData">
<router-link :to="`/productall/${id}`"></router-link>
</product-by-id>
</div>
</template>
in above code there is router link in v-if
<product-by-id :id="id" :test="`/productall/${id}`" v-if="productByIdData">
<router-link :to="`/productall/${id}`"></router-link>
</product-by-id>
and that code is working, since if i console log there is "/productall/603aaaf5dead94fee94d2811"
but why my url is not change still "http://localhost:8080/productall" what i expected is "http://localhost:8080/productall/603aaaf5dead94fee94d2811"
I set up an example routing implementation. A couple of components with a router configuration.
/router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
import Home from '#/components/stackoverflow/router-params-example/Home'
import ProductAll from '#/components/stackoverflow/router-params-example/ProductAll'
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/productall/:id',
name: 'productall',
component: ProductAll,
props: true
}
]
export default new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
App.vue
<template>
<div id="app" class="container">
<router-view></router-view>
</div>
</template>
Home.vue
<template>
<div class="parent">
<h4>Home</h4>
<div class="row">
<div class="col-md-6">
<router-link class="btn btn-primary" :to="{ name: 'productall', params: { id: productId } }">Product All</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
productId: '603aaaf5dead94fee94d2811'
}
}
}
</script>
ProductAll.vue
<template>
<div class="product-all">
<h4>Product All</h4>
<div class="row">
<div class="col-md-6">
<router-link class="btn btn-secondary" :to="{ name: 'home' }">Back</router-link>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: String,
required: true
}
}
}
</script>

Data not updating when API changed on Vue Js

Ok, I have a problem, here I make a data post with a tag, and when I click the tag the other data posts are not updated by the tag.
i'm get the api with created function, Do I have to use vuex?
can everyone help me, thanks very much
this is my template
<div class="col-md-4 mb-4" v-for="post in posts" :key="post.id">
<div class="card h-100 shadow-sm border-0 rounded-lg">
<div class="card-img">
<img :src="path+'/storage/posts/'+post.image" class="w-100"
style="height: 200px;object-fit: cover;border-top-left-radius: .3rem;border-top-right-radius: .3rem;">
</div>
<div class="card-body">
<router-link :to="{name: 'detail_post', params: {slug: post.slug}}"
class="text-dark text-decoration-none">
<h6>{{ post.title }}</h6>
</router-link>
</div>
<div class="card-footer bg-white">
<i class="fa fa-calendar" aria-hidden="true"></i> {{ post.created_at }}
</div>
</div>
</div>
this is my JavaScript
<script>
//import axios
import axios from 'axios'
export default {
name: 'PostIndex',
data() {
return {
path: axios.defaults.baseURL,
posts: []
}
},
created() {
//get post homepage
axios.get(`/api/tag/${this.$route.params.slug}`).then(response => {
this.posts = response.data.data.data;
})
}
}
</script>