Przycisk Enter w polu input w Vue

0

Witajcie.
Mam mały problem z Vue. Robię swój pierwszy projekt z użyciem Vue: https://pastebin.com/69XiaTQ7

<template>
  <div>
    <div class="row mb-3">
      <div class="col-3">
        <div class="input-group">
          <input
            v-model="search"
            class="form-control"
            placeholder="Szukaj..."
            type="text"
          >
          <div class="input-group-append">
            <button class="btn btn-primary" type="button" @click.prevent="handleSearch">
              <font-awesome-icon icon="fas fa-search"/>
            </button>
          </div>
        </div>
      </div>

            <div class="col-2">
              <div class="input-group">
                <label for="pageOption" class="mt-2 mr-2">Na stronie</label>
                <select class="form-control" v-model="perPage" @change="handlePerPage" id="pageOption">
                  <option v-for="page in pageOptions" :key="page" :value="page">{{ page }}</option>
                </select>
              </div>
            </div>
    </div>


    <table class="table table-hover">
      <thead>
      <tr>
        <th class="table-head">#</th>
<!--        <th v-for="column in columns" :key="column" @click="sortByColumn(column)"-->
<!--            class="table-head">-->
<!--          {{ column | columnHead }}-->
<!--          <span v-if="column === sortedColumn">-->
<!--                            <font-awesome-icon v-if="order === 'asc' "  icon="fas fa-angle-up" />-->
<!--                            <font-awesome-icon v-else icon="fas fa-angle-down" />-->
<!--            </span>-->
<!--        </th>-->
        <th v-for="(label, column) in headers" :key="column" @click="sortByColumn(column)" class="table-head">
          {{ label | columnHead }}
          <span v-if="column === sortedColumn">
                            <font-awesome-icon v-if="order === 'asc'"  icon="fas fa-angle-up" />
                            <font-awesome-icon v-else icon="fas fa-angle-down" />
            </span>
        </th>
        <th class="table-head">Opcje</th>
      </tr>
      </thead>
      <tbody>
      <tr class="" v-if="tableData.length === 0">
        <td class="lead text-center" :colspan="columns.length + 1">Brak danych do wyświetlenia.</td>
      </tr>
      <tr v-for="(data, key1) in tableData" :key="data.id" class="m-datatable__row" v-else>
        <td>{{ serialNumber(key1) }}</td>
        <td v-for="(value, key) in data" @click="editRecord(data.id)" style="cursor: pointer">{{ value }}</td>
        <td><button class="btn btn-danger" @click="prepareRemove(data.id)"><font-awesome-icon icon="fas fa-trash" /></button></td>
      </tr>
      </tbody>
    </table>
    <nav v-if="pagination && tableData.length > 0">
      <ul class="pagination">
        <li class="page-item" :class="{'disabled' : currentPage === 1}">
          <a class="page-link" href="#" @click.prevent="changePage(currentPage - 1)">Poprzednia</a>
        </li>
        <li v-for="page in pagesNumber" class="page-item"
            :class="{'active': page == pagination.meta.current_page}">
          <a href="javascript:void(0)" @click.prevent="changePage(page)" class="page-link">{{ page }}</a>
        </li>
        <li class="page-item" :class="{'disabled': currentPage === pagination.meta.last_page }">
          <a class="page-link" href="#" @click.prevent="changePage(currentPage + 1)">Następna</a>
        </li>
        <span style="margin-top: 8px;"> &nbsp; <i>Wyświetlam {{ pagination.data.length }} z {{ pagination.meta.total }} wyników.</i></span>
      </ul>
    </nav>

  </div>
</template>

<script type="text/ecmascript-6">
import axios from 'axios';
import Vue from 'vue';
import 'vuejs-datatable/dist/themes/bootstrap-4.esm';
import {
  VuejsDatatableFactory,
  IDataFnParams,
  IDisplayHandlerParam,
  ITableContentParam,
  TColumnsDefinition,
  VueDatatable
} from 'vuejs-datatable';

Vue.use(VuejsDatatableFactory, VueDatatable);
import Swal from 'sweetalert2';

export default {
  props: {
    fetchUrl: {type: String, required: true},
    columns: {type: Array, required: true},
    headers: {type: Object, required: true},
    routeName: {type: String, required: true},
    showUrl: {type: String, required: false},
  },
  data() {
    return {
      tableData: [],
      url: '',
      pagination: {
        meta: {to: 1, from: 1}
      },
      offset: 4,
      currentPage: 1,
      perPage: 100,
      sortedColumn: this.columns[0],
      order: 'asc',
      search: '',
      pageOptions: [100, 200, 500, 1000],
    }
  },
  watch: {
    fetchUrl: {
      handler: function (fetchUrl) {
        this.url = fetchUrl
      },
      immediate: true
    }
  },
  created() {
    console.log(this.fetchUrl);
    return this.fetchData()
  },
  computed: {
    /**
     * Get the pages number array for displaying in the pagination.
     * */
    pagesNumber() {
      if (!this.pagination.meta.to) {
        return []
      }
      let from = this.pagination.meta.current_page - this.offset
      if (from < 1) {
        from = 1
      }
      let to = from + (this.offset * 2)
      if (to >= this.pagination.meta.last_page) {
        to = this.pagination.meta.last_page
      }
      let pagesArray = []
      for (let page = from; page <= to; page++) {
        pagesArray.push(page)
      }
      return pagesArray
    },
    /**
     * Get the total data displayed in the current page.
     * */
    totalData() {
      return (this.pagination.meta.to - this.pagination.meta.from) + 1
    }
  },
  methods: {
    fetchData() {
      let dataFetchUrl = `${this.url}&page=${this.currentPage}&column=${this.sortedColumn}&order=${this.order}&per_page=${this.perPage}&search=${this.search}`
      axios.get(dataFetchUrl)
        .then(({data}) => {
          this.pagination = data
          this.tableData = data.data
        }).catch(error => this.tableData = [])
    },
    /**
     * Get the serial number.
     * @param key
     * */
    serialNumber(key) {
      return (this.currentPage - 1) * this.perPage + 1 + key
    },
    /**
     * Change the page.
     * @param pageNumber
     */
    changePage(pageNumber) {
      this.currentPage = pageNumber
      this.fetchData()
    },
    /**
     * Sort the data by column.
     * */
    sortByColumn(column) {
      if (column === this.sortedColumn) {
        this.order = (this.order === 'asc') ? 'desc' : 'asc'
      } else {
        this.sortedColumn = column
        this.order = 'asc'
      }
      this.fetchData()
    },
    handleSearch() {
      this.fetchData()
    },
    handlePerPage($event) {
      this.perPage = $event.target.value;
      this.fetchData()
    },

    recordLink(id) {
      return this.routeName + `/${id.toString()}`
    },
    editRecordLink(id) {
      return this.routeName + `/${id.toString()}/edit`
    },
    showRecord(id) {
      const recordLink = this.recordLink(id);
      this.$router.push({path: recordLink});
    },
    editRecord(id) {
      const editRecordLink = this.editRecordLink(id);
      this.$router.push({path: editRecordLink});
    },
    deleteRecord(id) {
      let self = this;
      axios.post(this.$apiAdress + '/api/' + this.routeName + '/' + id + '?token=' + localStorage.getItem("api_token"), {
        _method: 'DELETE'
      })
        .then(function (response) {
          Swal.fire(
            'Sukces!',
            'Rekord usunięty poprawnie!',
            'success'
          )
          self.fetchData();
        }).catch(function (error) {
        console.log(error);
        self.$router.push({path: '/login'});
      });
    },
    prepareRemove(id){
      const removeId = id;
      Swal.fire({
        title: 'Czy na pewno',
        text: "Chcesz usunąć ten rekord?",
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#d33',
        cancelButtonColor: '#3085d6',
        confirmButtonText: 'Tak, usuń!',
        cancelButtonText: 'Anuluj',
        buttonsStyling: true
      }).then((isConfirm) => {
        // now 'this' depends on the lexical enviroment.
        if(isConfirm.value === true) {
          this.deleteRecord(removeId);
        }
      });
    }


    ///
  },
  filters: {
    columnHead(value) {
      return value.split('_').join(' ').toUpperCase()
    }
  },
  name: 'DataTable'
}
</script>

<style scoped>
</style>

Wszystko działa poprawnie. Mam problem z wyszukiwarką.

Aby wyszukać jakąś frazę muszkę kliknąć ręcznie na guziczek - wciśnięcie przycisku ENTER nic nie daje.

W jaki sposób mogę to poprawić?:)

0
v-on:keyup.enter="handleSearch"

Ogólnie to polecam używanie jakiś sensownych kontrolek typu <b-table>

https://bootstrap-vue.org/docs/components/table

0

Rozwiązanie zasugerowane przez @Botek powinno zadziałać https://vuejs.org/v2/guide/events.html#Key-Modifiers bo dokumentacja pokazuje podobny przykład.

Ja nie jestem, aż takim specem od Vue, ale zawsze istnieje sposób, żeby zrobić to "normalnie", jeśli modyfikator nie działa, bo to jedynie kilka dodatkowych linijek

<input
  v-model="search"
  class="form-control"
  placeholder="Szukaj..."
  type="text"
  v-on:keyup="handleSearchInput"
>
{
  methods: {
    handleSearchInput(e) {
      if (e.key.toLowerCase() === 'enter') {
        this.handleSearch();
      }
    } 
  }
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1