Vue.js - Calling a component's method from Vue instance - vuejs2

I have a created a Vue instance and a global component. How can I call the component's method from my Vue instance?
In my Vue instance I did this:
methods: {
handleTabClick: function(tab, event) {
if (tab.name == 'log') {
call loadLog function in log component
}
}
}
Then my component is defined as this:
Vue.component('jettLog', {
props: ['shop'],
data() {
return {
log: [],
logLoading : true
}
},
methods: {
loadLog: function() {
console.log("Load");
},
},
});
How can I call jettLog's function loadLog from handleTabClick()?
I see different explanations and now I am wondering what's the best way to do it?
Thanks!

Register a global event bus whixh is an empty vue instance like this:
Var EventBus = new Vue();
in your vue instance emit an event with EventVus.$emit()
methods: {
handleTabClick: function(tab, event) {
if (tab.name == 'log') {
EventBus.$emit('log-event')
}
}
}
$emit() takes two arguments:
1: event name
2. event data (optional)
In the created hook of jettLog component set up an event listener on the EventBus and perform your logic when a paticular event is emitted
Vue.component('jettLog', {
props: ['shop'],
data() {
return {
log: [],
logLoading : true
}
},
created(){
var self = this;
EventBus.$on('log-event', function(eventData){
self.loadLog();
});
},
methods: {
loadLog: function() {
console.log("Load");
},
},
});
Check this out for more info

Related

Vue watch not triggerring on elements in array

I have two components. One of them creates instances of the other one and adds them to an array then I try to watch on it to execute some functions, but it never triggers. My structure looks something like this:
const Child = Vue.extend({
data() {
triggerMe: false
},
methods: {
triggerSomething: function() {
console.log('It's called for sure');
this.triggerMe = true;
}
}
});
const Parent = Vue.extend({
data() {
children: []
},
components: {
child: Child
},
methods: {
addChild: function() {
this.children.push(new Child());
this.children[this.children.length - 1].$watch('triggerMe', _ => console.log('Never called'));
}
}
});
It works just right if it's the only one. How to fix that?
What I found is that $watch only triggers when component is mounted to some element in document. Other approach is needed:
<scipt id="parent-template">
<child
#trigger="triggerThat"
></child>
</script>
<script>
// in Child
this.$emit('trigger', someData);
// in Parent
methods: {
triggerThat: function(data) {
console.log('I can hear you');
console.log(data);
}
}
</script>

Action is not defined as a method in the component vue.js

I'm trying to access an action as a method in component, But got error of
this.delete_notifaction is not a function
notifaction.js
export const actions = {
add_notifaction({ commit }, notifaction) {
commit("ADD_NOTIFACTION", notifaction);
},
delete_notifaction({ commit }, notificationToRemove) {
commit('DELETE_NOTIFACTION', notificationToRemove)
}
};
store/index.js
modules : {
notifaction
},
Component.vue
methods: mapActions('notifaction',["delete_notifaction"]),
mounted() {
this.delete_notifaction(this.notification);
}
Any Help?
Try this
methods: {
...mapActions(['delete_notifaction']),
}
See here for spread syntax
https://stackoverflow.com/a/48137766/10118668

nested object reactivity vue js

I have the following setup for my vue application
var store = {
...
state: {
currentCustomer:{},
},
};
current customer has a property that is an object called payment method
app:
var app= new Vue({
el:'#application',
data: {
sharedState: store.state
}
});
and a couple of components:
Vue.component('user_search', {
template: '#user_search-template',
data() {
return {
sharedState: store.state
}
},
methods: {
getCustomerData: function () {
this.sharedState.currentCustomer(c);
}
mounted: function () {
...
}
});
and
Vue.component('paymentdetails',{
template: '#payment_details_template',
data(){
return{
sharedState: store.state
}
},
mounted:function(){
...
}});
The issue is like this. The payment method component does not bind to the payment details object that is nested inside the current customer object
any suggestions?
Yeah, I think what you are looking for is a computed property for accessing the data.
Vue.component('paymentdetails',{
template: '#payment_details_template',
computed{
sharedState() {
return store.state
}
},
mounted:function(){
...
}});
Maybe give that a try and see how it works.

The prop object's property is undefined in refresh function

I use Vue.js and have a component. I pass a prop "request" to that component:
<adjustments-list
v-if="request"
:request="request"
/>
In the component I'm able to do this:
<text-input
:value="request.id"
/>
It works that is the value of "id" is displayed.
In props section of component:
props: {
request: Object
In mounted hook of component:
async mounted () {
await this.refresh()
},
In refresh function of component:
async refresh () {
console.log('this.request.id =', this.request.id)
if (this.request.id) {
const data = await requestApi.getRequestResultAdjustmentByReqId(this.request.id)
}
},
The this.request.id is undefined.
I'm not sure why.
If the request property is asynchronously available to the component then, you have to use combination of watchers like:
// adjustments-list component
new Vue({
props: {
request: Object
},
data() {
return {
apiData: null
}
},
watch: {
request(newValue, _oldValue) {
this.refresh(newValue);
}
},
mounted: function () {
// Do something here
},
methods: {
refresh (request) {
if (request.id) {
// Using promise instead of async-await
requestApi.getRequestResultAdjustmentByReqId(request.id)
.then(() => this.apiData = data);
}
}
}
});
Also, note that, mounted should be a plain old JS function and not an async function. That's the lifecycle method of the component supposed to behave in particular way.

Call component methods outside component

I am fairly new to Vue.js and I might be thinking about this the wrong way, in which case I would really appreciate the help.
I have a component defined as below:
Vue.component('btn', {
data() {
return {
active: false
};
},
props: ['type', 'msg'],
template: "<button class='btn__{{ type }}'><div class='la-ball-scale-multiple' v-show='active'><div></div><div></div><div></div></div>{{ msg }}</button>",
methods: {
start: function() {
this.active = true;
},
stop: function() {
this.active = false;
}
}
});
and I can add the btn component multiple times on any document, like this:
<btn type="primary" msg="Submit" #click="test"></btn>
When I click on it, it should do whatever is defined in test, which is in the root vue instance as a method.
However, I want to call the component's method, start in the test method. I also want to be able to call the component's stop method when I am done with the code logic inside test.
I don't think exposing the methods as events within the component and then calling this.$broadcast is a solution because, if I have two components, both of them seem to set active to true with this solution.
Any help please?
You could pass in your test function as a prop (called onclick for example) and then pass the context of your btn component as an argument to the test function. That way, you could access start and stop.
test:
test: function(e, btn) {
btn.start();
// ...
btn.stop();
}
btn:
Vue.component('btn', {
data() {
return {
active: false
};
},
props: ['type', 'msg', 'onclick'],
template: "<button class='btn__{{ type }}' #click="btnClick($event)"><div class='la-ball-scale-multiple' v-show='active'><div></div><div></div><div></div></div>{{ msg }}</button>",
methods: {
start: function() {
this.active = true;
},
stop: function() {
this.active = false;
},
btnClick: function(e) {
this.onclick(e, this); // call your onclick handler in the context of this component
},
}
});
custom element:
<btn type="primary" msg="Submit" :onclick="test"></btn>
Have a look at the JSFiddle:
https://jsfiddle.net/2a5os24x/6/