1
votes

I am trying to access the props in my vue component (child) below from another vue component (Parent). I am basically trying to reset the :selected value to null after the user selects an option from the dropdown menu.

 <template>
    <ul class="dropdown-menu" v-if="showMenu">
      <li v-for="option in options">
        <a href="javascript:void(0)"></a>
      </li>
    </ul>
  </div>
</template>
<script>
import { directive as onClickaway } from "vue-clickaway";
export default {
  directives: {
    onClickaway
  },
  data() {
    return {
      showMenu: false,
      placeholderText: "Please select an item"
    };
  },
  props: {
    selected: {},
    placeholder: [String],
  },
  },

  methods: {
    updateOptions(option) {
      this.showMenu = false;
      this.$emit("input", this.selectedOption);
    },
  }
};

</script>
1
What does the code for updateOption() in the parent component look like?Lanny Bose
@LannyBose oh, theres no code for it in the parent component, its from the child component.penguin
Sorry, I mean onColourSelectionLanny Bose
@LannyBose public onColourSelection(val: any) { this.colourId = val.id; } this is pretty much it, colourOptions are the colours obtained from the API as an array.penguin

1 Answers

1
votes

The first thing I notice in your parent template is that you're hard-coding the selected prop to {} which means it will never change. In addition, you're immediately throwing away the selected prop in the child's mounted hook with:

  mounted() {
    this.selectedOption = this.selected;
  }

...which means even if you change the prop from the parent, it won't do anything.

I'm going to suggest a refactoring of your code to use v-model in a way that the Dropdown never actually stores the selected value, but rather relies on the parent to store state (link to Vue docs).

Parent.vue

<template>
  <dropdown
    // other options skipped for clarity

    v-model="selected"
  ></dropdown>
</template>

<script>
export default {
  data() {
    return {
      selected: undefined
    }
  }
}
</script>

As you see in the Vue docs, v-model is just a convention for passing a prop called value and listening to an event called input. So in your child, you need to refactor slightly. Specifically, we're going to get rid of your intermediary value selectedOption:

Child.vue

<template>
  <!-- other divs hidden for clarity -->

  <input
    @click="toggleMenu()"
    v-model="value[attr]" // I am unsure that this is the right choice 
    type="text">

    <ul class="dropdown-menu" v-if="showMenu">
      <li v-for="option in options">
        <a href="javascript:void(0)" @click="updateOption(option)">{{ option[attr] }}</a>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showMenu: false,
      placeholderText: "Please select an item"
    };
  },
  props: {
    value: {}, // changed from selected
    attr: String,
  },

  methods: {
    updateOption(option) {
      this.showMenu = false;
      this.$emit('input', this.selectedOption);
    },
  }
};

</script>

The only place I'm unsure of your intended behavior is in your Child <input> tag. You had a v-model for the input, but it doesn't look like you're doing anything when someone types into that input (such as searching the color names, or whatever). Since typing in that input doesn't currently do anything. It may make more sense to make it a <div> that looks like an input but isn't actually type-able. Perhaps...

  <div @click="toggleMenu()">
    {{ value[attr] }}
  </div>