Как сортировать по аббревиатуре, когда в vue используются как аббревиатура, так и полное имя

#vue.js

#vue.js

Вопрос:

Я пытаюсь создать функцию сортировки, в которой пользователь будет нажимать на разные штаты на карте США, и когда они нажимают на это состояние, отображается список городов, принадлежащих этому штату.

Так, например, у меня есть кнопка «Все», которая отображает все города в США, но если они нажимают на другой штат, тогда города необходимо отфильтровать до этих штатов.

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

Я бы хотел, чтобы мой фильтр мог сортировать как по полному имени, так и по аббревиатуре.

Итак, если я нажму на штат Алабама на карте, будут показаны города, в которых есть либо «Алабама», либо «Алабама».

Вот мой код

 <template>
  <div class="row">
    <div class="col-md-12">
      <div class="card">
        <div class="card-body" id="sow-index">
          <div class="row">
            <div class="col-md-8">
              <div class="form-group row">
                <div class="col-sm-6">
                  <div class="btn-group btn-maps" role="group">
                    <button type="button" class="btn" v-on:click="selectedState = 'All'">All</button>
                    <button v-for="state in states" type="button" class="btn" v-on:click="selectedState = state">
                    <img :src="stateImage(state)">
                    <span>{{state}}</span>
                    </button>
                  </div>
                </div>
                <div class="col-sm-6">
                  <input type="text" class="form-control" v-model="search">
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-sm-12">
              <table class="table">
                <thead>
                  <tr>
                    <th>Name</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="city in displayCities">
                    <td>{{city.name}}</td>
                  </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
  
 export default {
  data() {
    return {
      selectedState: 'All',
      meta: {},
      states: ['AL', 'CA', 'KS', 'OH'],
      search: '',
      state: 'All',
      cities: [],
    }
  },
  computed: {
    stateCities() {
      return ('All' === this.selectedState) ? this.cities.filter(city => {
        city.state === this.selectedState
      });
    },
    filteredCities() {
      return ('' === this.search) 
        ? this.stateCities 
        : this.stateCities.filter(city => this.getSearchString(city).indexOf(this.search.toLowerCase()) > -1);
    },
  },
  methods: {
    getSearchString(city) {
      let string = city.name;
      return string.replace('null', '').trim().toLowerCase();
    },
    stateImage(state) {
      return "/states/image_"   state   ".jpg";
    },
    allCities() {
      axios.get('/api/state/cities').then((response) => {
        this.cities = response.data.cities;
      })
    }
  },
  mounted() {
      this.allCities();
  }
}
  

На данный момент я добавил только 4 состояния в свой код.

Вот пример вывода городов

     cities: array(50)
        0: 
            name: Athens
            state: Alabama
        1: 
            name: Greenville
            state: AL

  

Комментарии:

1. Кроме того, mounted не должно быть в вашем methods объекте

Ответ №1:

Похоже, вам нужно, чтобы ваши states значения содержали как сокращение, так и полное имя.

Например

 data: () => ({
  selectedState: null,
  states: [{
    name: "Alabama",
    abbr: "AL"
  }, {
    name: "California",
    abbr: "CA"
  }, {
    name: "Kansas",
    abbr: "KS"
  }, {
    name: "Ohio",
    abbr: "OH"
  }],
  search: '',
  cities: [],
})
  

В вашем шаблоне привяжите эти значения объекта к selectedState

 <button
  type="button"
  class="btn"
  @click="selectedState = null"
>All</button>
<button 
  v-for="state in states"
  :key="state.abbr"
  type="button"
  class="btn"
  @click="selectedState = state"
>
  <img :src="`/states/image_${state.abbr}.jpg`"> <!-- 👈 don't use methods for rendering -->
  <span>{{state.abbr}}</span>
</button>
  

Затем в вашем вычисляемом методе используйте оба свойства для сопоставления

 stateCities: ({ selectedState, cities }) => {
  if (selectedState) {
    return cities.filter(({ state }) =>
      selectedState.abbr === state || selectedState.name === state)
  }
  return cities
}