Nuxt.js after page refresh meta are filled from config instead of head method - vue.js

I had problem with meta in nuxt.js app. I want to fill dynamic meta tags in one detail page
--pages
----event
-----_id.vue
When I navigate on web site via link all work great. But if I just refresh page, meta tags use value from nuxt.config.js. For instance I got 'SiteTitle Nuxt.config.js' instead of 'SiteTitle - Some event title'.
Nuxt version 2.15.3
nuxt.config.js
export default {
head: {
titleTemplate: '%s - SiteTitle',
title: 'SiteTitle Nuxt.config.js',
htmlAttrs: {
lang: 'en'
},
meta: [
{charset: 'utf-8'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
{hid: 'description', name: 'description', content: ''}
],
link: [
{rel: 'icon', type: 'image/x-icon', href: '/favicon.ico'}
]
}
components: true,
buildModules: [
'#nuxt/typescript-build',
'#nuxtjs/vuetify',
],
modules: [`enter code here`
'#nuxtjs/axios'
],
vuetify: {
customVariables: ['~/assets/variables.scss'],
},
axios: {
baseURL: 'https://api.someurl.com',
}
}
And _id.vue file
<template>
<v-card class="mt-6 mb-5" outlined>
<v-card-title>{{ model.title }}</v-card-title>
</v-card>
</template>
<script lang="ts">
import {Component, Vue} from "nuxt-property-decorator"
import {EventModel} from "~/api/models/EventModel";
import EventApi from "~/api/EventApi";
#Component({
async asyncData({params, $axios}) {
const eventApi = new EventApi($axios)
const model = await eventApi.get(parseInt(params.id))
return { model: model };
},
head(this: EventPage): object {
return {
title: "SiteTitle - " + this.model.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.model.shortDescription
}
]
}
},
})
export default class EventPage extends Vue {
model = {} as EventModel
async fetch() {
}
}
</script>
I tried to call api in fetch, in this case meta values always have valid value when I refresh page, but Facebook Sharing Debugger get meta from nuxt.config.js in this case, and this solution is not suitable
Thanks for your help

You can do one thing
Create one plugin in that you can use this on router.beforeEach like this:
app.router.beforeEach(async(to, _, next) => {
document.title = to.meta.pageTitle ? ('Specify title - ' + ${to.meta.pageTitle}) :'Default Title';
})
In your router file you can do something like this:
{
path: '/path',
name: 'Name',
component: Component,
meta: {
pageTitle: 'Change Password'
}
}

Related

Nuxt 3: nuxt-socket-io throwing Cannot add property registeredWatchers

I'm trying to setup nuxt-socket-io on a Nuxt 3 project. I followed all the setup steps in the nuxt-socket-io documentation but it's throwing the following Error:
Cannot add property registeredWatchers, object is not extensible.
Does anyone know what it means? What I'm missing?
Here's what my code looks like:
nuxt.config.js:
export default defineNuxtConfig({
modules: [
'#nuxtjs/tailwindcss',
'nuxt-socket-io',
],
app: {
head: {
title: 'Nuxt Dojo',
meta: [
{ name: 'description', content: 'Everything about Nuxt 3'},
],
link: [
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons'}
]
}
},
runtimeConfig: {
public: {
apiUrl: process.env.API_URL,
},
},
io: {
// module options
sockets: [{
name: 'main',
url: 'http://localhost:4000'
}]
},
})
pages/index.vue:
<template>
<div>
<h2 class="text-xl">Index</h2>
<p>This project should become a messaging app.</p>
</div>
</template>
<script setup>
const socket = useNuxtApp().$nuxtSocket({
name: 'main',
channel: '/',
emitTimeout: 1000,
});
/* Listen for events: */
socket.on('message', (msg, cb) => {
console.log({ msg, cb });
});
</script>

vuejs3, cannot add dynamic title and description with usehead meta package

I have been trying to use Vuejs3 useHead package and add dynamic title and decription meta, but i get $route is undefined.... i need help...
<router-link :to="{name:'productDetails', params:{id:rope._id, title:rope.title, price: rope.price, description:rope.description, quantity:rope.totalQuantity}}">
peoductDetails.vue:
setup(){
useHead({
title: this.$route.params.title,
meta: [
{
name: `description`,
content: `blalala`
},
],
})
},
You need to use useRoute() in order to access the router, since in the setup hook this does not refer to the component instance.
setup(){
const route = useRoute();
useHead({
title: route.params.title,
meta: [
{
name: `description`,
content: `blalala`
},
],
})
},

Adding dynamic meta tags fetched from API to nuxtjs static site

I have a static site with Nuxt and content coming in from Strapi. I want to dynamically set the meta tags that are fetched asynchronously.
My site has an index page which passes the fetched data to index-web or index-mobile through props.
let pageMeta: any
const apiBase: string = 'https://strapi.xyz.com'
export default Vue.extend({
components: { Greeting, Showcase, Features, Footer },
props: {
data: Map,
pageMeta,
},
data() {
return {
loading: true,
}
},
metaInfo(): any {
return {
meta: [
{
hid: 'description',
name: 'description',
content: pageMeta.description,
},
{
hid: 'author',
name: 'author',
content: pageMeta.author,
},
],
}
},
})
The prop being passed in a JSON parsed object.
Having done this, the generated site does not have the meta tags added in.
As mentioned, you need to access the property with .this.

How to get data to Quasar tree node from local JSON file

I am very new to Quasar, I want to display Quasar tree nodes from a Local JSON file and with on click of a particular node item I want to show some text.
As of now I am using Quasar tree like this.
<template>
<q-page class="flex fixed-left">
<q-tree
:nodes="simple"
node-key="label"
no-connectors
:expanded.sync="expanded"
text-color="blue"
></q-tree>
</q-page>
</template>
<style>
</style>
<script>
export default {
name: 'HelloWorld',
data () {
return {
expanded: [ 'Resources' ],
simple: [
{
label: 'Resources',
children: [
{
label: 'Projects',
children: [
{
label: 'Data sets' ,
children: [
{
label: 'Items',
}
]
},
{ label: 'Good recipe' }
]
},
{
label: 'Good service (disabled node with icon)',
icon: 'room_service',
disabled: true,
children: [
{ label: 'Prompt attention' },
{ label: 'Professional waiter' }
]
},
{
label: 'Pleasant surroundings (with icon)',
icon: 'photo',
children: [
{
label: 'Happy atmosphere (with image)',
img: 'https://cdn.quasar.dev/img/logo_calendar_128px.png'
},
{ label: 'Good table presentation' },
{ label: 'Pleasing decor' }
]
}
]
}
]
}
}
}
</script>
It was coming like this
Now I wanted to get these nodes from a local JSON file and on click on Items should display some text .
Please help me with this.
To import JSON in ECMAScript:
If you don't have a lot of JSON files and you have the permission to modify and convert them into JS files, you can follow this answer: https://stackoverflow.com/a/39855320/3241933
Then you should import the vanilla JS object into data().
Example solution:
<template>
<q-page class="flex fixed-left">
<q-tree
:nodes="simple"
node-key="label"
no-connectors
:expanded.sync="expanded"
text-color="blue"
></q-tree>
</q-page>
</template>
<style>
</style>
<script>
import jsonData from './data.js'
export default {
name: 'HelloWorld',
data () {
return {
expanded: [ 'Resources' ],
simple: jsonData
}
}
}
</script>
Make sure that your import is an array of object.

How to create dynamic links based on an API request

I am completely new to both vue.js and Javascript. How do I dynamically create nav links from an Axios request?
I am wanting to follow what's being done in the item section which is currently static information, but i want to dynamically return links based on whats returned in the json request.
import * as types from '../../mutation-types'
import lazyLoading from './lazyLoading'
import charts from './charts'
// gathering items from API
const url = 'http://localhost:8080/items/'
data: {
items: []
},
mounted() {
axios.get(url).then(response => {
this.results = items.data
})
}
// Sidebar links are statically created here
const state = {
items: [
{
name: 'Dashboard',
path: '/dashboard',
meta: {
icon: 'fa-tachometer',
link: 'dashboard/index.vue'
},
component: lazyLoading('dashboard', true)
},
{
name: 'Axios',
path: '/axiosDemo',
meta: {
auth: true,
icon: 'fa-rocket',
link: 'axios/index.vue'
},
component: lazyLoading('axios', true)
},
charts,
]
}
const mutations = {
[types.EXPAND_MENU] (state, menuItem) {
if (menuItem.index > -1) {
if (state.items[menuItem.index] && state.items[menuItem.index].meta) {
state.items[menuItem.index].meta.expanded = menuItem.expanded
}
} else if (menuItem.item && 'expanded' in menuItem.item.meta) {
menuItem.item.meta.expanded = menuItem.expanded
}
}
}
export default {
state,
mutations
}
I think what I am wanting to do is something like this (python example):
items:
for i in items_payload:
{
name: i.name,
path: i.url,
meta: {
icon: 'fa-tachometer',
link: i.name+'/index.vue'
},
},
How do I best accomplish this in vue.js? Any help would be appreciated. Thanks.
If you are making the api request from a component, you can create a list of links like follows:
// for demo purposes, let's say links are returned as an array of objects
[
{
href: '/path/to/page1',
linkText: 'Page 1'
},
{
href: '/path/to/page2',
linkText: 'Page 2'
}
]
// MyComponent.vue
<template>
<div class="sidebar">
<ul>
<li v-for="(item, index) in items" :key="index">
<a :href="item.href">{{ item.linkText }}</a>
</li>
</ul>
</div>
</template>
export default {
data () {
return {
links: []
}
},
mounted() {
axios.get(url).then(response => {
this.links = items.data
})
}
}