Add custom property to vuejs component - javascript

How do I set a custom property inside a vue component?
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
// This does not seem to work
this.item.customProperty = 'customProperty';
}
});

You can use Vue.set to add reactivity:
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
Vue.set(this.item, 'customProperty', 'customProperty');
}
});

It seems that you should use Object.assign:
var myComponent = Vue.extend({
data: function() {
return {
item: {}
}
},
created: function() {
// This does not seem to work
this.item = Object.assign(this.item, {customProperty:'customProperty'});
}
});

Related

How can I use a Global Mixin method from a Vue instance

Let's suppose that I have the following situation, using a Global Mixin to create a global helper method with Vue:
import Vue from "vue";
Vue.mixin({
methods: {
replaceString: function (word) {
return word.toLowerCase().replace(/\W/g, '');
}
}
});
let vm = new Vue({
methods: {
doSomething: function() {
console.log(this.replaceString('Hello World'); //helloword
}
}
});
I know that I can invoke the method inside the other methods, inside of the component and their childs. But how can I invoke the mixin method "replaceString" from the Vue instance "vm"?
I tried to use "vm.replaceString", but keeps returning "undefined".
Few changes to your code and it works:
You should change the definition of your mixin (var mixin instead of Vue.mixin)
Import the mixin to your new vue component (mixins = [mixin])
import Vue from "vue";
var mixin = {
methods: {
replaceString: function (word) {
return word.toLowerCase().replace(/\W/g, '');
}
}
};
let vm = new Vue({
mixins: [mixin]
methods: {
doSomething: function() {
console.log(this.replaceString('Hello World'); //helloword
}
}
});
I think this chunk o code is what you are looking for:
var mixin = {
methods: {
foo: function () {
console.log('foo')
},
conflicting: function () {
console.log('from mixin')
}
}
}
var vm = new Vue({
mixins: [mixin],
methods: {
bar: function () {
console.log('bar')
},
conflicting: function () {
console.log('from self')
}
}
})
vm.foo() // => "foo"
vm.bar() // => "bar"
vm.conflicting() // => "from self"
From the docs

Vue.js. Data property undefined

I'm trying to access my data property in my Vue.js component. Looks like I'm missing something obvious.
Here is a short version of my code. StoreFilter.vue is a wrapper for matfish2/vue-tables-2.
<template>
<store-filter :selected.sync="storeIds"></store-filter>
</template>
<script>
import StoreFilter from './Filters/StoreFilter';
export default {
components: {
StoreFilter
},
data() {
return {
options : {
requestFunction(data) {
console.log(this.storeIds); //undefined
return axios.get('/api/orders', {
params: data
}).catch(function (e) {
this.dispatch('error', e);
}.bind(this));
},
},
storeIds: [],
}
},
watch : {
storeIds(storeIds) {
this.refreshTable();
}
},
methods : {
refreshTable() {
this.$refs.table.refresh();
}
}
}
</script>
How to get storeIds from requestFunction?
Use a closure, see rewrite below.
data() {
let dataHolder = {};
dataHolder.storeIds = [];
dataHolder.options = {
requestFunction(data) {
// closure
console.log(dataHolder.storeIds); // not undefined
return axios.get('/api/orders', {
params: data
}).catch(function (e) {
this.dispatch('error', e);
}.bind(this));
}
}
return dataHolder;
}
I recommend using the created() way to handle this.
export default {
// whatever you got here
data () {
return {
options: {}
}
},
created () {
axios.get('/api/orders', { some: params }).then(response => this.options = response.data)
}
}

Vue - non parent child communication

When reading Vue document
Non parent-child communication
For practice, I tried to build an example to see if it works, below is my code:
I build two component and tried to use Vue instance bus to transport message from dudi-station to dudo-station while on-click, but it's not working.
Can anyone help? Thanks!
Vue.component('dudi-station', {
template: '<div #click="sentMsg">{{dudiMsg}}</div>',
data: function() {
return {
dudiMsg: 'Dudi!!',
}
},
methods: {
sentMsg: function() {
bus.$emit('callout', this.dudiMsg);
},
}
});
Vue.component('dudo-station', {
template: '<div>{{dudoMsg}}</div>',
data: function() {
return {
dudoMsg:'',
}
},
created: function() {
bus.$on('callout', function(value) {
this.dudoMsg = value;
console.log(value);
});
}
});
var bus = new Vue();
new Vue({
el: '#app',
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<dudi-station></dudi-station>
<dudo-station></dudo-station>
</div>
Use arrow function as event handler when receiving message in component from another component. It will help you with "this" keyword scope.
bus.$on('callout', function(value) {
this.dudoMsg = value;
console.log(value);
});
instead of this use it as below
bus.$on('callout', (value) => {
this.dudoMsg = value;
console.log(value);
});
Because in this statement:
bus.$on('callout', function(value) {
this.dudoMsg = value;
this this is not mean your vue instance.
You need to use arrow function to make sure that 'this' means the vue instance.
Like below:
Vue.component('dudi-station', {
template: '<div #click="sentMsg">{{dudiMsg}}</div>',
data: function() {
return {
dudiMsg: 'Dudi!!',
}
},
methods: {
sentMsg: function() {
bus.$emit('callout', this.dudiMsg);
},
}
});
Vue.component('dudo-station', {
template: '<div>{{dudoMsg}}</div>',
data: function() {
return {
dudoMsg:'',
}
},
created: function() {
bus.$on('callout',value => {
this.dudoMsg = value;
console.log(value);
});
}
});
var bus = new Vue();
new Vue({
el: '#app',
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<dudi-station></dudi-station>
<dudo-station></dudo-station>
</div>

How to fetch data from server in vue js?

I am trying to fetch data from the server using Vue + Vuex + Vue resource.On button click I want to hit Http request and show in list format .I tried like that.Here is my code
https://plnkr.co/edit/EAaEekLtoiGPvxkmAtrt?p=preview
// Code goes here
var store = new Vuex.Store({
state: {
Item: []
},
mutations: {
getItems: function (state) {
}
},
actions: {
fetchData:function (context) {
this.$http.get('/data.json', function(v1users)
{
// this.$set('v1_user',v1users);
});
}
}
})
var httprequest = Vue.extend({
"template": '#http_template',
data: function () {
return {
items: store.state.Item
}
},
methods: {
fetchData: function () {
store.dispatch('fetchData')
},
}
})
Vue.component('httprequest', httprequest);
var app = new Vue({
el: '#App',
data: {},
})
;
any udpdate?
Try using Vue.http.get instead of this.$http.get.
Vuex doesn't have access to $http directly from instance.

Vue.js inheritance call parent method

Is it possible to use method overriding in Vue.js?
var SomeClassA = Vue.extend({
methods: {
someFunction: function() {
// ClassA some stuff
}
}
});
var SomeClassB = SomeClassA.extend({
methods: {
someFunction: function() {
// CALL SomeClassA.someFunction
}
}
});
I want to call ClassA someFunction from ClassB someFunction. Is it even possible?
No, vue doesn't work with a direct inheritance model. You can't A.extend an component, as far as I know. It's parent-child relationships work mainly through props and events.
There are however three solutions:
1. Passing props (parent-child)
var SomeComponentA = Vue.extend({
methods: {
someFunction: function () {
// ClassA some stuff
}
}
});
var SomeComponentB = Vue.extend({
props: [ 'someFunctionParent' ],
methods: {
someFunction: function () {
// Do your stuff
this.someFunctionParent();
}
}
});
and in the template of SomeComponentA:
<some-component-b someFunctionParent="someFunction"></some-component-b>
2. Mixins
If this is common functionality that you want to use in other places, using a mixin might be more idiomatic:
var mixin = {
methods: {
someFunction: function() {
// ...
}
}
};
var SomeComponentA = Vue.extend({
mixins: [ mixin ],
methods: {
}
});
var SomeComponentB = Vue.extend({
methods: {
someFunctionExtended: function () {
// Do your stuff
this.someFunction();
}
}
});
3. Calling parent props (parent-child, ugly)
// In someComponentB's 'someFunction':
this.$parent.$options.methods.someFunction(...);
In case someone's interested in a JustWorksTM solution:
var FooComponent = {
template: '<button #click="fooMethod()" v-text="buttonLabel"></button>',
data: function () {
return {
foo: 1,
bar: 'lorem',
buttonLabel: 'Click me',
}
},
methods: {
fooMethod: function () {
alert('called from FooComponent');
},
barMethod: function () {
alert('called from FooComponent');
},
}
}
var FooComponentSpecialised = {
extends: FooComponent,
data: function () {
return {
buttonLabel: 'Specialised click me',
zar: 'ipsum',
}
},
methods: {
fooMethod: function () {
FooComponent.methods.fooMethod.call(this);
alert('called from FooComponentSpecialised');
},
}
}
jsfiddle: https://jsfiddle.net/7b3tx0aw/2/
More info:
This solution is for devs that can't use TypeScript for some reason (which I think allows defining vue components as classes, which in turn allows full inheritance feature-set).
Further elaboration about the solution (whys and hows): https://github.com/vuejs/vue/issues/2977
This ain't that ugly, considering that no rocket science is used here (calling anonymous functions with the this pointer replaced should be no magic for any decent js dev).
How to use Function.prototype.call()
Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
Sample code:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
In case someone asks for a solution here is mine and works fine :
var SomeClassA = {
methods: {
someFunction: function () {
this.defaultSomeFunction();
},
// defaultSomeFunction acts like parent.someFunction() so call it in inheritance
defaultSomeFunction: function () {
// ClassA some stuff
},
},
};
var SomeClassB = {
extends: SomeClassA,
methods: {
someFunction: function () {
// Replace the wanted SomeClassA::someFunction()
this.defaultSomeFunction();
// Add custom code here
},
},
};
using juste extends from https://v2.vuejs.org/v2/api/#extends replaces the usage of Vue.extends()

Categories