1

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 class="close" style="align-self: flex-end; cursor: pointer;" @click="closeModal">x</span>
            <span class="label" 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>
3
  • In child this.modals is undefined Commented Nov 25, 2021 at 13:42
  • That's pretty weird to use same mixin in child and parent at the same time, instead you could emit button click event from child component and then in parent call powerbiFilterModal Commented Nov 25, 2021 at 13:48
  • @Radeanu could you add how it can be implemented? I checked with emit click but how a function can be triggered by using such event? Commented Nov 25, 2021 at 13:56

2 Answers 2

2

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;
    }
  }
});
Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.