Vuejs 2 make a global function and pass param - vue.js

In a component i am changing the title and description in mounted() but i want to make a global function so i can reuse the code below.
How can i achieve that?
window.document.title = 111;
document.head.querySelector('meta[name=description]').content = 222;
function getTitle(title){
return window.document.title = title;
}

I found the solution for this:
Vue.mixin({
methods: {
makeTitle: function (title) {
return window.document.title = title;
}
}
});
export default{
props: ['slug'],
data: function () {
return {
items: [],
}
},
mounted() {
this.makeTitle(this.slug);
},

Related

Start watcher after created() is done

My goal is to initially set up a data property when component is created and then set up a watcher on this property. The issue I am struggling with is the watcher catches initial property change in created method but this is not what I want. I would rather to watch data property only after initial change is made in created().
export default {
name: 'testComponent',
data() {
return {
testValue: 1;
}
},
watch: {
testValue() {
console.log('watcher catches!');
},
created() {
console.log(this.testValue);
this.testValue = 2;
console.log(this.testValue);
}
}
// CONSOLE OUTPUT: 1 -> watcher catches! -> 2
Can you tell me how to achieve behaviour like that?
No idea why you'd want that but you could simply do it like this:
export default {
name: 'testComponent',
data() {
return {
ready: false,
testValue: 1
}
},
watch: {
testValue() {
if (!this.ready) return;
console.log('watcher catches!');
},
created() {
this.testValue = 2;
this.ready = true;
}
}

VueJS $set not making new property in array of objects reactive

In my VueJS 2 component below, I can add the imgdata property to each question in the area.questions array. It works - I can see from the console.log that there are questions where imgdata has a value. But despite using $set it still isn't reactive, and the imgdata isn't there in the view! How can I make this reactive?
var componentOptions = {
props: ['area'],
data: function() {
return {
qIndex: 0,
};
},
mounted: function() {
var that = this;
that.init();
},
methods: {
init: function() {
var that = this;
if (that.area.questions.length > 0) {
that.area.questions.forEach(function(q) {
Util.HTTP('GET', '/api/v1/photos/' + q.id + '/qimage').then(function(response) {
var thisIndex = (that.area.questions.findIndex(entry => entry.id === q.id));
var thisQuestion = (that.area.questions.find(entry => entry.id === q.id));
thisQuestion.imgdata = response.data;
that.$set(that.area.questions, thisIndex, thisQuestion);
})
});
}
console.log("area.questions", that.area.questions);
},
Since area is a prop, you should not be attempting to make changes to it within this component.
The general idea is to emit an event for the parent component to listen to in order to update the data passed in.
For example
export default {
name: "ImageLoader",
props: {
area: Object
},
data: () => ({ qIndex: 0 }), // are you actually using this?
mounted () {
this.init()
},
methods: {
async init () {
const questions = await Promise.all(this.area.questions.map(async q => {
const res = await Util.HTTP("GET", `/api/v1/photos/${encodeURIComponent(q.id)}/qimage`)
return {
...q,
imgdata: res.data
}
}))
this.$emit("loaded", questions)
}
}
}
And in the parent
<image-loader :area="area" #loaded="updateAreaQuestions"/>
export default {
data: () => ({
area: {
questions: [/* questions go here */]
}
}),
methods: {
updateAreaQuestions(questions) {
this.area.questions = questions
}
}
}
Here that variable has a value of this but it's bound under the scope of function. So, you can create reactive property in data as below :
data: function() {
return {
qIndex: 0,
questions: []
};
}
Props can't be reactive so use :
that.$set(this.questions, thisIndex, thisQuestion);
And assign your API output to directly questions using this.questions.

VueJS How to access Mounted() variables in Methods

I'm new in Vue and would like assistance on how to access and use variables created in Mounted() in my methods.
I have this code
Template
<select class="controls" #change="getCatval()">
Script
mounted() {
var allcards = this.$refs.allcards;
var mixer = mixitup(allcards);
},
methods: {
getCatval() {
var category = event.target.value;
// I want to access mixer here;
}
}
I can't find a solution anywhere besides this example where I could call a method x from mounted() and pass mixer to it then use it inside my getCatval()
Is there an easier way to access those variables?
I will first suggest you to stop using var, and use the latest, let and const to declare variable
You have to first declare a variable in data():
data(){
return {
allcards: "",
mixer: ""
}
}
and then in your mounted():
mounted() {
this.allcards = this.$refs.allcards;
this.mixer = mixitup(this.allcards);
},
methods: {
getCatval() {
let category = event.target.value;
this.mixer
}
}
like Ninth Autumn said : object returned by the data function and props of your components are defined as attributes of the component, like your methods defined in the method attribute of a component, it's in this so you can use it everywhere in your component !
Here an example:
data() {
return {
yourVar: 'hello',
};
},
mounted() { this.sayHello(); },
method: {
sayHello() { console.log(this.yourVar); },
},
Update
you cannot pass any value outside if it's in block scope - Either you need to get it from a common place or set any common value
As I can see, var mixer = mixitup(allcards); is in the end acting as a function which does some operation with allcards passed to it and then returns a value.
1 - Place it to different helper file if mixitup is totally independent and not using any vue props used by your component
In your helper.js
const mixitup = cards => {
// Do some operation with cards
let modifiedCards = 'Hey I get returned by your function'
return modifiedCards
}
export default {
mixitup
}
And then in your vue file just import it and use it is as a method.
In yourVue.vue
import Helpers from '...path../helpers'
const mixitup = Helpers.mixitup
export default {
name: 'YourVue',
data: ...,
computed: ...,
mounted() {
const mixer = mixitup(allcards)
},
methods: {
mixitup, // this will make it as `vue` method and accessible through
this
getCatval() {
var category = event.target.value;
this.mixitup(allcards)
}
}
}
2- Use it as mixins if your mixitup dependent to your vue and have access to vue properties
In your yourVueMixins.js:
export default {
methods: {
mixitup(cards) {
// Do some operation with cards
let modifiedCards = 'Hey I get returned by your function'
return modifiedCards
}
}
}
And import it in your vue file:
import YourVueMixins from '...mixins../YourVueMixins'
const mixitup = Helpers.mixitup
export default {
name: 'YourVue',
mixins: [YourVueMixins] // this will have that function as vue property
data: ...,
computed: ...,
mounted() {
const mixer = this.mixitup(allcards)
},
methods: {
getCatval() {
var category = event.target.value;
this.mixitup(allcards)
}
}
}

Is it possible to exchange the render functions of VueJS-Components during runtime?

I've played around with vue-i18n and Vue.compile() and found a very static solution to my problem. While searching for a solution I've tried to dynamically set the render functions during runtime. Unfortunately without any success.
Out of curiosity: Is it possible to exchange the render functions of Components during runtime?
I try to do something like this:
{
props: {
toCompile: {
type: String,
required: true
},
callbackFn: {
type: Function,
default: () => {}
}
},
created (){
let res = Vue.compile(this.toCompile);
this.render = res.render;
this.staticRenderFns = res.staticRenderFns;
}
}
The following approach is working for me:
{
...
methods: {
render: function () {
var createElement = this.$createElement;
return (this._self._c || createElement)("div", {
staticClass: "element"
});
}
},
beforeCreate: function() {
this.$vnode.componentOptions.Ctor.options.render = this.$vnode.componentOptions.Ctor.options.methods.render.bind(this);
}
}
If your want slots as well, use the following render method:
render: function () {
var that = this,
createElement = (this._self._c || this.$createElement),
children = Object.keys(that.$slots).map(function(slot) {
return createElement('template', { slot }, that.$slots[slot]);
});
return createElement('div', [
createElement('component-element, {
attrs: that.$attrs,
on: that.$listeners,
scopedSlots: that.$scopedSlots,
}, children)
]);
}

How to pass a variable from a function in the component in Vue?

How to pass a variable from a function in the component in Vue?
This is my code:
export default {
name: 'app',
data: function () {
return{
city1: '',
city2: '',
metr: 0
}
},
created () {
ymaps.ready(init);
function init() {
$data.city1 = 'sdf'; // ?this to data of component?
Because you created an new function, the this inside it will be not point to the Vue component, but to the this of the function itself.
You can use an arrow function, or save the reference of the this, then use it later.
created() {
const self = this;
ymaps.init(init);
function init() {
self.city1 = 'sdf';
}
}
Or (better):
created() {
const init = () => {
this.city1 = 'sdf';
}
ymaps.init(init);
}