vue2 отключить ввод с несколькими компонентами - PullRequest
0 голосов
/ 27 апреля 2018

Vue 2 - отключить ввод - несколько компонентов

Привет всем,

Я изо всех сил пытаюсь решить проблему, в которой я хочу отключить другие поля ввода после ввода первого символа в другое поле ввода.

Я пытался решить эту проблему с помощью $ emit, @focus и других решений, и я все еще застрял. Я также не смог использовать ответы, которые можно найти здесь.

Отрывок:

const Autocomplete = {
  name: "autocomplete",
  props: {
    items: {
      type: Array,
      required: false,
      default: () => ['test']
    },
    isAsync: {
      type: Boolean,
      required: false,
      default: false
    },
    formLock: {
      type: Boolean,
    },
    formId: {
      type: String,
    }
  },

  data() {
    return {
      isOpen: false,
      results: [],
      search: "",
      isLoading: false,
      arrowCounter: 0,
    };
  },

  methods: {
    onChange() {
      // Let's warn the parent that a change was made
      this.$emit("input", this.search);

      // Is the data given by an outside ajax request?
      if (this.isAsync) {
        this.isLoading = true;
      } else {
        // Let's search our flat array
        this.filterResults();
        this.isOpen = true;
      }

      if (this.search.length === 0) {
        this.isOpen = false;
      }

      console.log(this.search.length);

    },

    disableOther() {
      var searchForms = document.getElementsByClassName('searchForm');
      for (i = 0; i < searchForms.length; i++) {

      }

      console.log(searchForms.length);

    },

    filterResults() {
      // first uncapitalize all the things
      this.results = this.items.filter(item => {
        return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
      });
    },
    setResult(result) {
      this.search = result;
      this.isOpen = false;
    },
    onArrowDown(evt) {
      if (this.arrowCounter < this.results.length) {
        this.arrowCounter = this.arrowCounter + 1;
      }
    },
    onArrowUp() {
      if (this.arrowCounter > 0) {
        this.arrowCounter = this.arrowCounter - 1;
      }
    },
    onEnter() {
      this.search = this.results[this.arrowCounter];
      this.isOpen = false;
      this.arrowCounter = -1;
    },
    handleClickOutside(evt) {
      if (!this.$el.contains(evt.target)) {
        this.isOpen = false;
        this.arrowCounter = -1;
      }
    }
  },

  mounted() {
    document.addEventListener("click", this.handleClickOutside);

  },
  destroyed() {
    document.removeEventListener("click", this.handleClickOutside);
  },

  template: `

    <div>
        <input type="text" @input="onChange" class="searchForm" v-model="search" @keyup.down="onArrowDown" @keyup.up="onArrowUp" @keyup.enter="onEnter" v-bind:disabled="formLock" @focus="disableOther" />
        <ul id="autocomplete-results" v-show="isOpen" class="autocomplete-results">
          <li class="loading" v-if="isLoading">
            Loading results...
          </li>
          <li v-else v-for="(result, i) in results" :key="i" @click="setResult(result)" class="autocomplete-result" :class="{ 'is-active': i === arrowCounter }">
            {{ result }}
          </li>
        </ul>
    </div>
    
        `,
};

new Vue({
  el: "#productSearchApp",
  name: "productSearchApp",

  data() {
    return {
      productName: [],
      productCatalog: [],
      lock: false,
      searchName: "searchForm",
      searchCatalog: "searchCatalog"
    }
  },

  mounted() {
    fetch("http://cormay.314-work.pl/wp-json/wp/v2/product")
      .then(response => response.json())
      .then((data) => {
        for (i = 0; i < data.length; i++) {
          this.productName.push(data[i].title.rendered);
        };
        for (i = 0; i < data.length; i++) {
          this.productCatalog.push(data[i].product_catalog);
        };
      })
  },

  components: {
    autocomplete: Autocomplete,
  },

  methods: {
    updateLock(updateLock) {
      this.lock = updateLock;
    }
  }
});
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="productSearchApp">
  <autocomplete :items="productName" :form-id="searchName"></autocomplete>
  <autocomplete :items="productCatalog" :form-id="searchCatalog"></autocomplete>
</div>

Спасибо!

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

Вы можете попробовать что-то вроде этого.

Вы заметите, что я передаю название модели взад-вперед, что может показаться неудобством для управления, но если бы вы сконфигурировали его как часть цикла v-for, оно бы им легко управлять.

Vue.component('custom-input', {
  props: ['value', 'disabled'],
  template: `
    <input
      :disabled="disabled"
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})
new Vue({
    el:'#app',
    data:{
      first: null,
      second: null,
      active: null
    },
    methods: {
      onChange(e, model){
        this.active = null
        if (e.length > 0) {
          this.active = model
        }
      }
    },
    
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<div id="app">
  <custom-input v-model="first" :disabled="active !== null && active !== 'first'" @input="onChange($event, 'first')">Foo</custom-input>
  <custom-input v-model="second" :disabled="active !== null && active !== 'second'" @input="onChange($event, 'second')">Bar</custom-input> 
</div>
0 голосов
/ 27 апреля 2018

Возможно, вы могли бы использовать менеджер состояний, например VueX или Свойства экземпляра ... как:

//  global state 
Vue.prototype.$state = new Vue({
  data: { 
    active: null
  }
})


//  input component
Vue.component('vue-input', {
  props: ['value'],
  template: `
      <label>
        <slot></slot>
        <input v-model="model" :disabled="disabled" />
      </label>
  `,
  data() {
    return {
      //  avoid mutation     
      model: this.value
    }
  },
  beforeDestroy() {
    //  reset state in case we remove the active component
    if (this.$state.active === this) this.$state.active = null;
  },
  watch: {
    model(value) {
      //  set active to 'this' if value length > 0 or null active value
      this.$state.active = value.length ? this : null;
    }
  },
  computed: {
    disabled() {
      //  disable if active is not null and not equal to 'this'
      return this.$state.active && this.$state.active !== this;
    }
  }
})


//  app instance  
new Vue({
  el: '#app',
  data: {
    foo: null,
    bar: null
  }
})
label {
  font: caption;
  display: flex;
  justify-content: space-between;
  width: 160px;
  margin-bottom: 10px;
}

input:disabled {
  background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.3/vue.js"></script>
<div id="app">
  <vue-input v-model="foo">Foo</vue-input>
  <vue-input v-model="bar">Bar</vue-input>
</div>
...