Vue.js - handling metadata with vue-simple-headful - vue.js

I use vue-simple-headful plugin to work with metadata in vue.js app , page title, description, keywords, etc...
I have the following setup in my vue app:
main.js
import vueHeadful from 'vue-simple-headful';
Vue.use(vueHeadful, {component: true});
component's function:
headful(vm) {
return {
title: this.category.header,
description: 'yay, a static description'
}
The page title is updated from this.category.header, but only once, during the first call to the component. Following calls to the component with the headful function do not update the page title.
I would like it to be dynamic, that is whenever component's function is called page title and other metadata is updated accordingly.

I ended up using vue-headful instead of vue-simple-headful. Following the example from How to set the Document with Vue.js has done the trick.

Related

How to set the page title in Vue 2, that will work on page load, from the component

I am trying to set the page title from the component as there are dynamic properties that will change the content of the title.
Using the examples I have found on here talk about setting the this.$route.meta.pageTitle. This only works when the page is navigated to via the application, not on a page refresh or load from bookmark.
I have tried to hook into all the lifecycle hooks, both in the router and the component, as well as adding a watcher in my root component.
How do I set the title on those load conditions?
In the component, you need to set the document.title rather than the route metadata.
created () {
this.$route.meta.title = `${myDynamicProp} - my site`
document.title = this.$route.meta.title;
}

Nuxt.js footer component is not executing code to retrieve data

We have a nuxt.js application which retrieves data from strapi. this works for all the other pages that we've created, but when we try to retrieve data for the <Footer /> it appears that the code is not executing.
This is the code that we use for retrieving on the index page:
export default {
async asyncData({ $strapi }) {
return {
homepage: await $strapi.find("homepage"),
};
},
}
All we change from page to page is the variable name and the value its finding.
This works on 10 - 12 pages.
On main pages we are able to retrieve the data of the footer with this code:
export default {
async asyncData({ $strapi }) {
return {
footer: await $strapi.find("footer")
};
},
}
However when we put this code in our footer component it doesn't appear to execute, as no variable was shown in the view explorer, and if we try an render anything form the {{footer}} then we get an error saying we've referenced something that doesn't exist.
Is there any reason why this code isn't executing in the footer component?
The asyncData hook can only be used on page components. The official documentation explains how you can work around this issue:
asyncData is only available for pages and you don't have access to this inside the hook.
Use the new fetch hook that is available in Nuxt 2.12 and later versions.
Make the API call in the mounted hook and set data properties when loaded. Downside: Won't work for server side rendering.
Make the API call in the asyncData method of the page component and pass the data as props to the sub components. Server rendering will work fine. Downside: the asyncData of the page might be less readable because it's loading the data for other components.

Vue/Nuxt: How to make a component be truly dynamic?

In order to use a dynamically-defined single page component, we use the component tag, thusly:
<component v-bind:is="componentName" :prop="someProperty"/>
...
import DynamicComponent from '#/components/DynamicComponent.vue';
...
components: {
DynamicComponent
},
props: {
componentName: String,
someProperty: null,
}
The problem is, this isn't really very dynamic at all, since every component we could ever possibly want to use here needs to be not only imported statically, but also registered in components.
We tried doing this, in order at least to avoid the need to import everything:
created() {
import(`#/components/${this.componentName}.vue`);
},
but of course this fails, as it seems that DynamicComponent must be defined before reaching created().
How can we use a component that is truly dynamic, i.e. imported and registered at runtime, given only its name?
From the documentation: Emphasis mine
<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component>
In the example above, currentTabComponent can contain either:
the name of a registered component,
or a component’s options object
If currentTabComponent is a data property of your component you can simply import the component definition and directly pass it to the component tag without having to define it on the current template.
Here is an example where the component content will change if you click on the Vue logo.
Like this:
<component :is="dynamic" />
...
setComponentName() {
this.dynamic = () => import(`#/components/${this.componentName}.vue`);
},
Solution for Nuxt only
As of now its possible to auto-import components in Nuxt (nuxt/components). If you do so, you have a bunch of components ready to be registered whenever you use them in your vue template e.g.:
<MyComponent some-property="some-value" />
If you want to have truly dynamic components combined with nuxt/components you can make use of the way Nuxt prepares the components automagically. I created a package which enables dynamic components for auto-imported components (you can check it out here: #blokwise/dynamic).
Long story short: with the package you are able to dynamically import your components like this:
<NuxtDynamic :name="componentName" some-property="some-value" />
Where componentName might be 'MyComponent'. The name can either be statically stored in a variable or even be dynamically created through some API call to your backend / CMS.
If you are interested in how the underlying magic works you can checkout this article: Crank up auto import for dynamic Nuxt.js components
According to the official Documentation: Starting from v2.13, Nuxt can auto import your components when used in your templates, to activate this feature, set components: true in your configuration
you are talking about async components. You simply need to use the following syntax to return the component definition with a promise.
Vue.component('componentName', function (resolve, reject) {
requestTemplate().then(function (response) {
// Pass the component definition to the resolve callback
resolve({
template: response
})
});
})

Dynamically decide when to use vue router

I have a big web application which I am building with vuejs and laravel.
Along the way, I have to switch between
<router-link></router-link> and <a></a> tags
so I build a template that I have a link on it I want it to automatically detect if vue <router-view></router-view>
is available otherwise just use the normal href tag
The below code is the function I have assigned to the click function but it turns out not to be working
try {
this.$router.push("/cart");
} catch (error) {
window.location.href = "/cart";
}
}
My question is
is there any way I can dynamically detect the presence of vue router and as well decide on which tag to use.
Either
window.location.href
or
this.$router.push()

Customize routerLink in Angular 5

In my application I am using routerLink to create my link as per according to parameter passed in routerLink.
<a [routerLink]="['/home/global/userprofile',UserId]">
Above code generate links with the userId provided, but I want to customize angular routerLink so that I can check if UserId is valid or not, if valid I will return the converted href link throught this and if not I will return blank or null url.
I can not use any other directive approach or pipe factories as I am using this routerLink code in several places in my project so I just not want to go and change each and every where that code is writtern. Can anyone guide me in this? I just need concept, I can write code for the idea.
If required, I can explain it more if any queries for this.
Instead of using routerLink directive, I suggest You to use a programmatical redirection in your component class, like this:
HTML component file
<a (click)="goToUserProfile(UserId)">Some link</a>
TS Component class:
import { Router } from '#angular/router';
constructor(private router: Router) {}
goToUserProfile(userId: number) {
if (/* userId verification*/) {
this.router.navigate(['/home/global/userprofile', userId]);
}
// do nothing
}
Otherwise, you can use a router guard, here are some useful links:
Angular Routing and navigation
Using Route Guards
Hope it helps.