I use metaInfo() function syntax, and return a titleTemplate function which binds to my root component property. I want the template to change when my property updated. I tested but it's not working. Maybe I missed something?
metaInfo() {
return {
// if no subcomponents specify a metaInfo.title, this title will be used
title: '',
// all titles will be injected into this template
titleTemplate: titleChunk => (this.locale === 'zh-cn'
? `${titleChunk} XXX`
: `${titleChunk} YYY`),
};
},
This should be possible indeed, but this in the titleTemplate fn might be set to a different component then the one you expect. More specifically, its probably the last component which triggered the update for that batchUpdate sequence. See the src code here: https://github.com/nuxt/vue-meta/blob/d7d15260aa9457907da2955d3719da2e3ca55cee/src/shared/getMetaInfo.js#L155
Could you please verify that this is really the component you expect it to be? If its not, the only solution for now is to set const self = this before the return and use self.locale instead of this.locale
Ah, right. arrow functions and scope binding is a tricky thing, because you can't re-bind them. Better go for titleTemplate(chunk){} if you need the this inside.
same problem.
Title changed only while page rendering. In browser there is no update of title(through computed property in titleTemplate function), it still the same as on page render.
@karakum Could you or @joshuajazleung please post a working/minimal reproduction?
@pimlie https://codesandbox.io/s/k2x31ly5oo
just open app in new window to see window title
@karakum Yeah, looks like titleTemplate is bound to the root component. that's why it doesn't have the computed props or data attributes available.
There is a hacky workaround though:
head() {
return {
title: { t: "Index title", c: this.newMessages },
titleTemplate: ({ t, c }) => {
return `校 胁邪褋 薪芯胁褘械 褋芯芯斜褖械薪懈褟: ${c} 褕褌 - ${t}`;
}
};
},
@manniL looks good, but what about default layout component. And I have to modify all pages for this title-object value.
I have this.newMessages in layout and head() / title are in pages components.
@karakum you can use head in layout as well 鈽猴笍 Maybe a higher order function could work for that (as @pimlie suggested).
@manniL @pimlie here my configuration example (layout(with titleTemplate) and page(with title))
https://codesandbox.io/s/v05kop794y
I don't understand about 'higher order function', can you explain and help modify my codesandbox to work properly?
I had another idea, could you please try this? (CSB doesnt work for me)
head() {
const newMessages = this.newMessages
return {
title: "Index title",
titleTemplate: function(t) {
return `校 胁邪褋 薪芯胁褘械 褋芯芯斜褖械薪懈褟: ${newMessages} 褕褌 - ${t}`;
}
};
},
@pimlie it doesn't work.
@karakum @joshuajazleung
The reason why this problem exists is due to how reactivity works in Vue and outside the scope of vue-meta (unless we refactor everything which we might do for vue-meta 2.0). The proof for this is because in the csb you get 0 messages and not undefined messages.
If metaInfo (or head in Nuxt) is a function then that function is treated as a computed property. Vue will automatically create an observer to track changes to that computed property. The way Vue does that (in a very short explanation) is by just calling the method and track which variables are accessed by the method, so when one of those variables changes it knows the return value of the function (might) changes too.
Thats why I thought my previous idea would work, the titleTemplate function is called from deep within vue-meta completely outside the scope of the component observers. So by setting a local newMessages variable _before_ we return the metaInfo object we explicitly tell Vue that head() is depending on the this.newMessages variable.
The following example does work as expected with the local variable fix but not when I use this.locale directly within titleTemplate (it's an adaptation of the basic-render example). So I think @karakum has a second issue with his code, what exactly eludes me for the moment. Try to debug if the value of newMessages really changes in your layout
import Vue from 'vue'
import VueMeta from 'vue-meta'
Vue.use(VueMeta)
Vue.component('child', {
name: 'Child',
props: ['page'],
data () {
return {
locale: 'nl'
}
},
render (h) {
return h('h3', null, this.page)
},
metaInfo () {
const locale = this.locale
return {
title: this.page,
titleTemplate: (c) => (locale === 'nl' ? 'Hallo Wereld' : 'Hello World') + ` - ${c}`
}
}
})
const app = new Vue({
template: `
<div id="app">
<h1>Basic Render</h1>
<p>Inspect Element to see the meta info</p>
<child page="This is a prop"></child>
</div>
`
}).$mount('#app')
setTimeout(() => {
app.$children[0].locale = 'en'
}, 2000)
@pimlie I take my words back - this realy worked! I don't know why it happend before, but now all right.
const cnt=this.newMessages in head() resolve issue;
Thanks a lot!
Great!
@joshuajazleung Please let us know if your issue is resolved as well by setting a local variable
Closing this as it should be resolved, please re-open or create a new issue if you are still experiencing issues
Most helpful comment
@karakum @joshuajazleung
The reason why this problem exists is due to how reactivity works in Vue and outside the scope of vue-meta (unless we refactor everything which we might do for vue-meta 2.0). The proof for this is because in the csb you get
0 messagesand notundefined messages.If
metaInfo(orheadin Nuxt) is a function then that function is treated as a computed property. Vue will automatically create an observer to track changes to that computed property. The way Vue does that (in a very short explanation) is by just calling the method and track which variables are accessed by the method, so when one of those variables changes it knows the return value of the function (might) changes too.Thats why I thought my previous idea would work, the
titleTemplatefunction is called from deep within vue-meta completely outside the scope of the component observers. So by setting a localnewMessagesvariable _before_ we return the metaInfo object we explicitly tell Vue thathead()is depending on thethis.newMessagesvariable.The following example does work as expected with the local variable fix but not when I use
this.localedirectly within titleTemplate (it's an adaptation of thebasic-renderexample). So I think @karakum has a second issue with his code, what exactly eludes me for the moment. Try to debug if the value ofnewMessagesreally changes in your layout