Automatikus kiegészítés - válasszuk opciót kattintással - vuejs

szavazat
0

Néhány évvel ezelőtt létrehozott egy autocomplete komponens vue irányuló projekt, amelyben veszek részt.

De ma észlelt egy kis hiba.

Amikor kiválasztom a lehetőséget szeretnék a kattintás az egér, a lehetőség nem kap továbbítani, mint látható az console.log (), hogy a példa. Ha rákattintok egy másik lehetőség újra, mi jelenik meg console.log ()az a lehetőség, előzőleg kiválasztott.

Ha tesz egy setTimeout( () => {}, 200)már érzékeli és bocsátanak ki a lehetőséget, de szerintem ez nem a legjobb megoldás ebben az esetben.

Bármilyen javaslat?

példa

const Autocomplete = {
  name: autocomplete,
  template: #autocomplete,
  props: {
    items: {
      type: Array,
      required: false,
      default: () => Array(150).fill().map((_, i) => `Fruit ${i+1}`)
    },
    isAsync: {
      type: Boolean,
      required: false,
      default: false
    }
  },

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

  methods: {
    onChange() {
      console.log( this.search)
      // Let's warn the parent that a change was made
      this.$emit(input, this.search);
    },
    setResult(result, i) {
      this.arrowCounter = i;
      this.search = result;
      this.isOpen = false;
    },
    showAll() {
      this.isOpen = !this.isOpen;
			(this.isOpen) ? this.results = this.items : this.results = [];
    },
  },
  computed: {
      filterResults() {
      // first uncapitalize all the things
      this.results = this.items.filter(item => {
        return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
      });
      
     
      return this.results;
    },
  },
  watch: {
    items: function(val, oldValue) {
      // actually compare them
      if (val.length !== oldValue.length) {
        this.results = val;
        this.isLoading = false;
      }
    }
  },
  mounted() {
    document.addEventListener(click, this.handleClickOutside);
  },
  destroyed() {
    document.removeEventListener(click, this.handleClickOutside);
  }
};

new Vue({
  el: #app,
  name: app,
  components: {
    autocomplete: Autocomplete
  }
});
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

.autocomplete {
  position: relative;
  width: 130px;
}

.autocomplete-results {
  padding: 0;
  margin: 0;
  border: 1px solid #eeeeee;
  height: 120px;
  overflow: auto;
  width: 100%;
}

.autocomplete-result {
  list-style: none;
  text-align: left;
  padding: 4px 2px;
  cursor: pointer;
}

.autocomplete-result.is-active,
.autocomplete-result:hover {
  background-color: #4aae9b;
  color: white;
}
<script src=https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js></script>
<div id=app>
  <autocomplete />

</div>

<script type=text/x-template id=autocomplete>
  <div class=autocomplete>
    <input type=text @blur=onChange v-model=search  @click=showAll />
    <ul id=autocomplete-results v-show=isOpen ref=scrollContainer class=autocomplete-results>
      <li class=loading v-if=isLoading>
        Loading results...
      </li>
      <li ref=options v-else v-for=(result, i) in filterResults :key=i @click=setResult(result, i) class=autocomplete-result :class={ 'is-active': i === arrowCounter }>
        {{ result }}
      </li>
    </ul>

  </div>
</script>

A kérdést 13/02/2020 22:00
a forrás felhasználó
Más nyelveken...                            


2 válasz

szavazat
1

Ön által használt onBlur esemény, de a lövése, ha rákattint kívül, és mielőtt az onclick a tétel hallgató, így az értéke nem frissült.

Használja onChange esemény rögzítés adatokat, ha felhasználó bármit a bemeneti és a hívás onChange () metódus belsejében setResult ().

const Autocomplete = {
  name: "autocomplete",
  template: "#autocomplete",
  props: {
    items: {
      type: Array,
      required: false,
      default: () => Array(150).fill().map((_, i) => `Fruit ${i+1}`)
    },
    isAsync: {
      type: Boolean,
      required: false,
      default: false
    }
  },

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

  methods: {
    onChange() {
      console.log( this.search)
      // Let's warn the parent that a change was made
      this.$emit("input", this.search);
    },
    setResult(result, i) {
      this.arrowCounter = i;
      this.search = result;
      this.isOpen = false;
      // Fire onChange, because it won't do it on blur
      this.onChange();
    },
    showAll() {
      this.isOpen = !this.isOpen;
			(this.isOpen) ? this.results = this.items : this.results = [];
    },
  },
  computed: {
      filterResults() {
      // first uncapitalize all the things
      this.results = this.items.filter(item => {
        return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
      });
      
     
      return this.results;
    },
  },
  watch: {
    items: function(val, oldValue) {
      // actually compare them
      if (val.length !== oldValue.length) {
        this.results = val;
        this.isLoading = false;
      }
    }
  },
  mounted() {
    document.addEventListener("click", this.handleClickOutside);
  },
  destroyed() {
    document.removeEventListener("click", this.handleClickOutside);
  }
};

new Vue({
  el: "#app",
  name: "app",
  components: {
    autocomplete: Autocomplete
  }
});
#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  color: #2c3e50;
}

.autocomplete {
  position: relative;
  width: 130px;
}

.autocomplete-results {
  padding: 0;
  margin: 0;
  border: 1px solid #eeeeee;
  height: 120px;
  overflow: auto;
  width: 100%;
}

.autocomplete-result {
  list-style: none;
  text-align: left;
  padding: 4px 2px;
  cursor: pointer;
}

.autocomplete-result.is-active,
.autocomplete-result:hover {
  background-color: #4aae9b;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
  <autocomplete />

</div>

<script type="text/x-template" id="autocomplete">
  <div class="autocomplete">
    <input type="text" @change="onChange" v-model="search"  @click="showAll" />
    <ul id="autocomplete-results" v-show="isOpen" ref="scrollContainer" class="autocomplete-results">
      <li class="loading" v-if="isLoading">
        Loading results...
      </li>
      <li ref="options" v-else v-for="(result, i) in filterResults" :key="i" @click="setResult(result, i)" class="autocomplete-result" :class="{ 'is-active': i === arrowCounter }">
        {{ result }}
      </li>
    </ul>

  </div>
</script>

Válaszolt 13/02/2020 22:25
a forrás felhasználó

szavazat
1

blura rossz esemény itt használni, és szerintem te át bonyolítja azt. Egyszerűen hívja fel emita setResult:

setResult(result, i) {
      this.arrowCounter = i;
      this.search = result;
      this.isOpen = false;     
      this.$emit("input", this.search);
    },
Válaszolt 13/02/2020 22:44
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more