I have 2 components: parent and child and one mixin. I am trying to use one function in both of them. Call mixin function from child component, which is in parent component. This mixin function also changes data var from parent component, which in child referenced in props.
However, on this line of code:
this.modals.filter = 'block'; occurs error: TypeError: Cannot set properties of undefined (setting 'filter')
I cannot get why, as modals.filter is referenced in props already?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
</head>
<body>
<div id="example" style="width:100%;height:100%">
<parent></parent>
</div>
</body>
<script>
var myMixin = {
methods: {
powerbiFilterModal: function() {
this.modals.filter = 'block';
if (this.embed.channelName, this.filters.columnName, this.filters.tableName) {
// Some other functions
// ...
console.log(this.embed.channelName, this.filters.columnName, this.filters.tableName);
// Hide modal
this.modals.filter = 'none';
// Clear inputs
this.embed.channelName = '';
this.filters.columnName = '';
this.filters.tableName = '';
}
}
}
};
Vue.component('child', {
mixins: [myMixin],
template: `
<div :style="{ display: filterOverlay }">
<span style="align-self: flex-end; cursor: pointer;" @click="closeModal">x</span>
<span style="align-self: center; margin-bottom: 4%">Filter Settings: </span>
<input type="text" placeholder="Define channel name" v-model.trim="channelName">
<input type="text" placeholder="Define filter name" v-model.trim="columnName">
<input type="text" placeholder="Define table to filter" v-model.trim="tableName">
<button @click="powerbiFilterModal">Subscribe & Send</button>
</div>
`,
props: {
filterOverlay: {
type: String,
required: false,
default: 'none'
},
channelName: {
type: String,
required: false
},
columnName: {
type: String,
required: false
},
tableName: {
type: String,
required: false
}
},
methods: {
closeModal: function() {
this.$emit('emitEv', 'none');
}
}
});
Vue.component('parent', {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<child @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function() {
return {
modals: {
filter: 'none'
},
embed: {
channelName: ''
},
filters: {
columnName: '',
tableName: ''
}
}
},
methods: {
changeOverlay: function(value) {
this.modals.filter = value;
}
}
});
new Vue({
el: "#example"
});
</script>
</html>
CodePudding user response:
Explaining my comment
Child component
Vue.component("child", {
// mixins: [myMixin], remove mixin from child
template: `
<div>
<!-- bla bla bla -->
<button @click="$emit('fire')">Subscribe & Send</button>
</div>
...
`
});
Parent component
Vue.component("parent", {
mixins: [myMixin],
template: `
<div>
<button @click="powerbiFilterModal">Set Filters</button>
<!-- HERE we listen for event (fire) from child and call powerbiFilterModal method from mixin -->
<child @fire="powerbiFilterModal" @emitEv="changeOverlay" v-bind:filter-overlay="modals.filter">Child</child>
</div>
`,
data: function () {
return {
modals: {
filter: "none"
},
embed: {
channelName: ""
},
filters: {
columnName: "",
tableName: ""
}
};
},
methods: {
changeOverlay: function (value) {
this.modals.filter = value;
}
}
});
CodePudding user response:
powerbiFilterModal()
is referencing this.modals
, which is OK if it's used in the parent component, but the child component has no such data, so the mixin will cause an error if called within the child.