overriding child method with parent method in vue.js - javascript

suppose I have a child component
save-button.vue
<template>
<!--some code like label/div-->
<button #click="save">Save</button>
<!--some code like label/div-->
</template>
<script>
export default{
methods:{
save(){
//some code here
}
}
}
</script>
parent.vue
<save-button/>
...
<script>
export default{
methods:{
save(){
//some codes
}
}
}
</script>
Now in the parent component, I need to override the save function in save-button.vue with the save function in parent.vue. How should I do it? The save function in save-button.vue is shared by a lot of other components

You can pass the function as a non-required prop.
Parent
<template>
<div id="app">Using Parent:
<SaveButton :save="save"/>Using Default:
<SaveButton/>
</div>
</template>
<script>
import SaveButton from "./components/SaveButton";
export default {
components: {
SaveButton
},
methods: {
save() {
console.log("Save from Parent !");
}
}
};
</script>
Child
<template>
<div>
<button #click="saveClicked">Save</button>
</div>
</template>
<script>
export default {
props: {
save: {
type: Function,
default: null
}
},
methods: {
saveClicked() {
if (this.save) {
this.save();
return;
}
console.log("Save from the Child !");
}
}
};
</script>

Related

Vue Component Event triggers but doesnt do anything

This is my code:
Tablecomponent:
<template>
<rowcomponent #reloadTable="fetchData(pagination.current_page)" :item_data="item" :isDOMadd="false" :workflowoffer_id="workflowoffer_id"></rowcomponent >
</template
<script>
import rowcomponent from "./rowcomponent";
export default{
methods :{
fetchData(url){
console.log('test');
},
components: {
rowcomponent,
},
}
}
</script>
Rowcomponent:
<script>
export default{
methods :{
safeData(){
console.log('safe');
this.$emit('reloadTable');
}
},
}
</script>
Console Output:
safe
The Vue Event gets triggered (vue-devtool) but it doesnt do anything
i Know it should work, but it doesnt. Has anyone some solutions or tips what it could be.
UPDATE: So i found the error, but i cant explain it ^^
I add this line in the Tablecomponent in export default {...}:
name: "TableComponent",
and now it works**
Since you didn't share your row-component completely I made a working example. Can you please look at this and compare with yours ?
Parent component:
<template>
<div id="app">
<rowcomponent #reloadTable="reloadTable" />
</div>
</template>
<script>
import rowcomponent from "./components/rowcomponent";
export default {
name: "App",
methods: {
reloadTable () {
console.log("test")
}
},
components: {
rowcomponent
}
};
</script>
rowcomponent
<template>
<div class="hello">
click me to see the results
<button #click="safeData"> click me </button>
</div>
</template>
<script>
export default {
name: "rowcomponent",
methods :{
safeData(){
console.log('safe');
this.$emit('reloadTable');
}
}
};
</script>
Output will be : safe and test

Vue JS - Problem with incrementing value by one in parent component using $emit

I am learning $emit in Vue JS, I decided to create a value called counter in the child component then increment by one when the button is clicked, but I decided to write all the logic in the parent component using $emit
But every time I click on the button, the value does not increase although the method works
LifeCycles.vue
<template>
<div>
<p>{{counter}}</p>
<button #click="add">Click me</button>
</div>
</template>
<script>
export default {
data() {
return {
counter: 0,
};
},
methods: {
add() {
this.$emit('updated', this.counter)
}
},
};
</script>
HeadlineLifeCycle.vue
<template>
<div>
<LifeCycles #updated="usefulMethod" />
</div>
</template>
<script>
import LifeCycles from "./LifeCycles.vue";
export default {
components: {
LifeCycles,
},
methods: {
usefulMethod: function(counter) {
console.log(counter++)
}
}
};
</script>
This is because you're not incrementing count in the child component where it's placed in its data:
const lifecycles = Vue.component('lifecycles', {
template: "#lifecycles",
data() { return { counter: 0 } },
methods: {
add() { this.$emit('updated', ++this.counter); } // fix
}
});
new Vue({
el: "#headlinelifecycle",
components: { lifecycles },
methods: {
usefulMethod: function(counter) { console.log(counter); }
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template id="lifecycles">
<div>
<p>{{counter}}</p>
<button #click="add">Click me</button>
</div>
</template>
<div id="headlinelifecycle"><LifeCycles #updated="usefulMethod" /></div>
If you want to control LifeCycles from the parent state:
const lifecycles = Vue.component('lifecycles', {
template: "#lifecycles",
props: ['counter'],
methods: {
add() { this.$emit('updated', this.counter+1); }
}
});
new Vue({
el: "#headlinelifecycle",
components: { lifecycles },
data() { return { counter: 0 } },
methods: {
usefulMethod: function(counter) {
this.counter = counter;
console.log(this.counter);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template id="lifecycles">
<div>
<p>{{counter}}</p>
<button #click="add">Click me</button>
</div>
</template>
<div id="headlinelifecycle">
<LifeCycles #updated="usefulMethod" :counter="counter" />
</div>
The line
this.$emit('updated', this.counter)
is not emitting this.counter reference, so any time you click on the button, you actually are emmiting the counter initial value which is 0.
So, if you really need to do all the logic in the parent component, you have to define the counter variable in parent component:
lifecycle.vue
<template>
<div>
<p>{{counter}}</p>
<button #click="$emit('clicked')">Click me</button>
</div>
</template>
HeadlineLifeCycle.vue
<template>
<div>
<LifeCycles #clicked="increase" />
</div>
</template>
<script>
import LifeCycles from "./LifeCycles.vue";
export default {
components: {
LifeCycles,
},
data() {
return {
counter: 0,
};
},
methods: {
increase: function() {
console.log(this.counter++)
}
}
};
</script>
You also can pass a variable to the lifecycle.vue as model and manage its value in lifecycle component.

Toggle a variable value with emit

I want to set the 'visualizacao' variable to true in a click of a button, but this button is in another component.
COMPONENT 1 with the visualizacao variable
<template>
<div>
<card-patrimonial v-if="!visualizacao"/>
<visualizacao-patrimonial v-else/>
</div>
</template>
<script>
import Patrimonial from '#/modules/Casos/Patrimonial/_components/Patrimonial.vue';
import VisualizacaoPatrimonial from '#/modules/Casos/Patrimonial/_components/VisualizacaoPatrimonial.vue';
export default {
name: "CasosPartes",
components: {
'card-patrimonial': Patrimonial,
'visualizacao-patrimonial': VisualizacaoPatrimonial,
},
data(){
return{
visualizacao: false
}
}
}
</script>
COMPONENT 2 with the button to change the variable visualizacao of component 1
<template>
<button>Change component</button
</template>
<script>
export default {
data() {
return {
}
}
}
</script>
How can I do this with emit?
In Component2:
<template>
<button #click="changeComponent()">Change component</button
</template>
<script>
export default {
data() {
return {
}
},
methods: {
changeComponent(){
this.$emit("listenButtonEvent");
}
}
}
</script>
In Component 1:
<template>
<div>
<card-patrimonial #changeComponent="changeVisualizacao" v-if="!visualizacao"/>
<visualizacao-patrimonial v-else/>
</div>
</template>
<script>
import Patrimonial from '#/modules/Casos/Patrimonial/_components/Patrimonial.vue';
import VisualizacaoPatrimonial from '#/modules/Casos/Patrimonial/_components/VisualizacaoPatrimonial.vue';
export default {
name: "CasosPartes",
components: {
'card-patrimonial': Patrimonial,
'visualizacao-patrimonial': VisualizacaoPatrimonial,
},
data(){
return{
visualizacao: false
}
},
methods: {
changeVisualizacao(){
this.visualizacao = true;
}
}
}
</script>
Here is an example: https://jsfiddle.net/z2v3nsuq/
const Clicker = {
template: `<button #click="$emit('clicked')">Click me</button>`,
};
new Vue({
el: '#app',
components: { Clicker },
data() {
return {
clickCount: 0,
};
},
});

Vue.js pass callback through a prop.

I've got a component that looks like this:
<template>
<div>
<pagination class="center" :pagination="pagination" :callback="loadData" :options="paginationOptions"></pagination>
</div>
</template>
<script>
import Pagination from 'vue-bootstrap-pagination';
export default {
components: { Pagination },
props: ['pagination', 'loadData'],
data() {
return {
paginationOptions: {
offset: 5,
previousText: 'Terug',
nextText: 'Volgende',
alwaysShowPrevNext: false
}
}
}
}
</script>
In another component I use that ^:
<template>
<pagination :pagination="pagination" :callback="loadData" :options="paginationOptions"></pagination>
</template>
<script>
export default {
loadData() {
this.fetchMessages(this.pagination.current_page);
}
//fetchMessages
}
</script>
But I receive the error:
Invalid prop: type check failed for prop "callback". Expected Function, got Undefined.
(found in component <pagination>)
Is it not possible in Vue.js 2.0 to pass a callback?
I think your second component may not be written accurately, your loadData callback should be in methods:
<template>
<pagination :pagination="pagination" :callback="loadData" :options="paginationOptions"></pagination>
</template>
<script>
export default {
methods: {
loadData() {
this.fetchMessages(this.pagination.current_page);
}
}
}
</script>
App.vue
<template>
<div>
<pre>{{ request }}</pre>
<pagination #callback="loadData"></pagination>
</div>
</template>
<script>
import Pagination from './Pagination.vue'
export default {
name: 'App',
components: { Pagination },
data() {
return {
request: {}
}
},
methods: {
loadData(request) {
this.request = request
}
}
}
</script>
Pagination.vue:
<template>
<div>
<button #click="$emit('callback', { currentPage: 10, whatEver: 7 })">call it back</button>
</div>
</template>
<script>
export default {
name: 'Pagination'
}
</script>
https://codesandbox.io/embed/8xyy4m9kq8

Mount parent component in child

I have two files named Recursive.vue and Value.vue.
In the first instance Recursive is the parent. Mounting Recursive in Recursive goes great, same for mounting Value in Recursive and after that Value in Value.
But when I've mounted Value in Recursive and trying to mount Recursive in Value after that I get the following error:
[Vue warn]: Failed to mount component: template or render function not defined.
(found in component <recursive>)
How can I make my problem work?
This is what my files are looking like:
Recursive
<template>
<div class="recursive">
<h1 #click="toggle">{{comps}}</h1>
<div v-if="isEven">
Hello
<value :comps="comps"></value>
</div>
</div>
</template>
<script>
import Value from './Value.vue'
export default {
name: 'recursive',
components: {
Value
},
props: {
comps: Number
},
computed: {
isEven () {
return this.comps % 2 == 0;
}
},
methods: {
toggle () {
this.comps++;
}
}
}
</script>
Value
<template>
<div class="value">
<h1 #click="toggle">{{comps}}</h1>
<div v-if="isEven">
<recursive :comps="comps"></recursive>
</div>
</div>
</template>
<script>
import Recursive from './Recursive.vue'
export default {
name: 'value',
components: {
Recursive
},
props: {
comps: Number
},
computed: {
isEven () {
return this.comps % 2 == 0;
}
},
methods: {
toggle () {
this.comps++;
}
}
}
</script>
Mounter
<template>
<div class="mounter">
<h1>HI</h1>
<recursive :comps="comps"></recursive>
</div>
</template>
<script>
import Recursive from './Recursive'
export default {
name: 'mounter',
components: {
Recursive
},
data () {
return {
comps: 0
}
}
}
</script>
I had a similar problem before. The only way out was declaring the component as "global", because importing it in the component which actually required it never worked.
new Vue({
...
})
Vue.component('recursive', require('./Recursive'))
Then you can just use without importing:
// Mounted
<template>
<div class="mounter">
<h1>HI</h1>
<recursive :comps="comps"></recursive>
</div>
</template>
<script>
export default {
name: 'mounter',
data () {
return {
comps: 0
}
}
}
</script>

Categories