Vue.js custom select component with v-model

前端 未结 2 2013
粉色の甜心
粉色の甜心 2020-12-21 07:56

I want to create a custom select component in Vue.js. Since I need specific options styling, I need to create \'select\' made of div\'s etc that looks and acts like a real

相关标签:
2条回答
  • 2020-12-21 08:47

    As Vue Guide said:

    v-model is essentially syntax sugar for updating data on user input events, plus special care for some edge cases.

    The syntax sugar will be like:

    the directive=v-model will bind value, then listen input event to make change like v-bind:value="val" v-on:input="val = $event.target.value"

    So for your use case, you need to create one prop=value, then emit the selected option with event=input.

    Like below demo (bind/emit the whole option object):

    Vue.config.productionTip = false
    Vue.component('child', {
      template: `<div class="component-container"  @click="showOptions = !showOptions">
            <div class="component__select">
                <span class="component__select--name">{{value ? value.name : 'Select Fruit'}}</span>
                
                <span class="c-arrow-down" v-if="!showOptions"></span>
                <span class="c-arrow-up" v-if="showOptions"></span>
            </div>
            <ul class="component__select-options" v-if="showOptions" >
                <li class="select--option" v-for="option in options" @click="selectOption(option)">
                    <label> <input type="checkbox" :value="option"/> {{option.name}}</label>
                </li>
            </ul>
        </div>`,
    
      methods: {
        selectOption(option) {
          this.$emit('input', option)
        }
      },
      data: () => ({
      	showOptions: false
      }),
      props: ['options', 'value']
    });
    
    var vm = new Vue({
      el: '#app',
      data: () => ({
    	options: [
      {id: 0, name: 'Apple'},
      {id: 1, name: 'Banana'},
      {id: 2, name: 'Orange'},
      {id: 2, name: 'Strawberry'},
      ],
      selectedFruit: ''
      }),
    })
     .component__select {
       height: 38px;
       background-color: #F5F7FA;
       border: 1px solid #ffffdffffd;
       line-height: 38px;
       display: grid;
       max-width: 500px;
       grid-template-columns: 10fr 1fr;
     }
    
     .component__select--name {
       font-size: 0.8rem;
       padding: 0 0 0 25px;
       cursor: pointer;
     }
    
     .c-arrow-down {
       justify-self: end;
     }
    
     .component__select-options {
       max-height: 180px;
       border: 1px solid #ffffdffffd;
       border-top: none;
       overflow: auto;
       position: absolute;
       z-index: 1500;
       max-width: 500px;
       width: 500px;
       margin: 0;
       padding: 0;
     }
    
     .select--option {
       height: 35px;
       display: grid;
       align-content: center;
       padding: 0 0 0 25px;
       background-color: #f5f5fa;
       border-bottom: 1px solid #ffffdffffd;
     }
    
     .select--option:last-child {
       border-bottom: none;
     }
    
     .select--option:nth-child(2n) {
       background-color: #ffffff;
     }
     
     .select--option input{
       display: none;
     }
    
     .single-option {
       height: 55px;
       background-color: #2595ec;
       font-size: 0.8rem;
       border: 1px solid red;
     }
    
     .cust-sel {
       width: 200px;
       height: 38px;
       background-color: #f5f5fa;
       border: 1px solid #ffffdffffd;
     }
    
     .cust-sel:focus {
       outline-width: 0;
     }
    <script src="https://unpkg.com/vue@2.5.16/dist/vue.js"></script>
    <div id="app">
      <span> This is parent component</span>
      <p>I want to have data from select here:  "{{selectedFruit}}"</p>
      <child :options="options" v-model="selectedFruit"></child>
    </div>

    0 讨论(0)
  • 2020-12-21 08:51

    When using v-model on custom component all you need is to declare a prop named 'value' and when you need the component to chance it emit an 'input' event.

    Something like this:

    <template>
      <form @submit.prevent="$emit('onSearch',val)" class="form-perfil">
        <div class="form-group col-md-12">
          <input v-model="val" @input="$emit('input',val)" 
          placeholder="filtrar resultados" class="form-control">
        </div>
      </form>
    </template>
    <script>
    module.exports = {
      name: "CaixaFiltro",
      props: ["value"],
      data: _ => ({ val: "" }),
      created() {
        this.val = this.value
      }
    }
    </script>
    

    Then you can use (after register the component) it like this:

    <caixa-filtro v-model="textoBusca" @onSearch="listar"></caixa-filtro>
    

    You can find more detailed info there:

    0 讨论(0)
提交回复
热议问题