A
A
Alex2020-01-13 19:26:25
Vue.js
Alex, 2020-01-13 19:26:25

Click outside of vue component area?

It was necessary to make a calculator on vue. This calculator has selects, but since they were already styled using jquery styler throughout the site, I took the ready-made layout from it and based on this I created my own component with the same classes. Everything works as it should, but the catch is how to close the select if it is out of focus or if the click is outside of this element/component? There can be several selects in the calculator.
Below is the code and link to jsfiddle

const vSelect = {
  props: {
    name: {
      type: String,
      required: true
    },
    label: String,
    items: { 
      required: true
    },
    value: {
      required: true
    },
    fields: Object,
    
  },
  data () {
    return {
      selectedOption: null,
      opened: false
    }
  },
  computed: {
    currentValueName() {
      if( this.fields ) {
        return this.items.find(item => item.id == this.value).name;
      } else {
        return this.items[value];
      }
    }
  },
  created () {
    this.selectedOption = this.value;
  },
  watch: {
    value: {
      handler(newValue) {
        this.selectedOption = newValue;
      }
    }
  },
  methods: {
    selectItem(index) {
      this.$emit('input', index);
      this.opened = false;
    }
  },
  template: `
    <div class="form-item v-select">
      <label :for="name" v-if="label">{{ label }}</label>
      <div :class="['jq-selectbox', 'jqselect', {dropdown: opened, opened: opened}]">
        <select
          :id="name" 
          :name="name"
          class="not-styler"
          v-model="selectedOption"
        >
          <option 
            v-for="(option, o) in items"
            :key="fields ? option[fields.id] : o"
            :selected="(fields ? option[fields.id] : o) === value"
            :value="fields ? option[fields.id] : o"
          >
            {{ fields ? option[fields.value] : option }}
          </option>
        </select>
        <div class="jq-selectbox__select" @click="opened = !opened">
          <div class="jq-selectbox__select-text">{{ currentValueName }}</div>
          <div class="jq-selectbox__trigger">
            <div class="jq-selectbox__trigger-arrow"></div>
          </div>
        </div>
        <div class="jq-selectbox__dropdown" v-show="opened">
          <ul>
            <li 
              v-for="(option, o) in items"
              :key="fields ? option[fields.id] : o"
              :class="{selected: (fields ? option[fields.id] : o) === value}"
              @click="selectItem(fields ? option[fields.id] : o)"
            >
              {{ fields ? option[fields.value] : option }}
            </li>
          </ul>
        </div>
      </div>
    </div>`
};

new Vue({
  el: '#preorder',
  components: {
    'v-select': vSelect,
  },
  data() {
    return {
    order: 1,
      typeApartment: [
        {
          id: 1,
          name: 'Зал — 210 человек'
        },
        {
          id: 2,
          name: 'Зал — 420 человек'
        }
      ],
    }
  },
});

<div id="preorder">
  <v-select 
    :name="'type-apartment'" 
    :label="'Тип помещения'"
    :items="typeApartment"
    :fields="{ id: 'id', value: 'name' }"
    v-model="order"
  />
</div>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
0
0xD34F, 2020-01-13
@pilolin

https://www.npmjs.com/package/v-click-outside
Well, or you can do it yourself:

created() {
  const onClickOutside = e => this.opened = this.$el.contains(e.target) && this.opened;
  document.addEventListener('click', onClickOutside);
  this.$on('hook:beforeDestroy', () => document.removeEventListener('click', onClickOutside));
},

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question