Получить значение выбранного элемента в компоненте Vuetify множественный выбор - PullRequest
1 голос
/ 14 апреля 2019

В моем коде есть следующий v-select:

<v-select
    v-if='d.length'
    v-model='ci'
    :items='d'
    item-text='value.name'
    item-value='value.name'
    label='label'
    multiple='multiple'
    height='60'
    small-chips
    single-line
    solo
    @change='itemChanged'
  >
  <template v-slot:prepend-item v-if='multiple && title && d.length'>
    <v-list-tile
      ripple
      @click="action"
    >
      <v-list-tile-action>
        <v-icon :color="ci.length > 0 ? 'indigo darken-4' : ''">{{ icon }}</v-icon>
      </v-list-tile-action>
      <v-list-tile-content>
        <v-list-tile-title>{{title}}</v-list-tile-title>
      </v-list-tile-content>
    </v-list-tile>
    <v-divider class="mt-2"></v-divider>
  </template>
  <template v-slot:selection="{ item, index }">
    <v-chip v-if="index === 0">
      <span>{{ item.text }}</span>
    </v-chip>
    <span
      v-if="index === 1"
      class="grey--text caption"
    >(+{{ checkedItems.length - 1 }} others)</span>
  </template>
</v-select>

Он получает свою модель, предметы и другие защиты в качестве реквизита. Модель и Предметы - идентичные массивы объектов со следующей структурой:

{text: 'text', value: {name: 'foo'}}

Таким образом, практически все элементы выбираются при монтировании компонента.

Как только пользователь нажимает на элемент из списка, я хочу получить в моем методе itemChanged либо весь объект, либо хотя бы объект значения. На данный момент я хочу только консольный журнал полученного объекта:

itemChanged(value) {
  console.log('Changed item', value);
}

Но он печатает весь массив модели, за вычетом нажатого элемента

Пытался использовать return-object, пытался изменить значение элемента и изменить структуру объектов - всегда один и тот же результат.

Есть идеи, как получить только объект / значение элемента, по которому щелкнули мышью?

1 Ответ

1 голос
/ 14 апреля 2019

Работает ли что-то подобное или я неправильно понимаю ваш вопрос?Это выводит выбранные элементы (как объекты) обратно на страницу против console.log(...).

Зеркало CodePen


Редактировать: (отвечаяваш вопрос ниже) ~~ Slot Props ~~: (не путать с «именованными слотами») по сути позволяет вам брать свойства у дочернего компонента и использовать их для рендеринга в родительском. Вы можете узнать больше о слотах с ограниченным пространством (также известных как «реквизиты слотов») здесь

Возьмите следующий блок кода, например:

          <template v-slot:item='data'>
            <v-list-tile-content>
              <v-list-tile-title>
                {{ data.item.firstName }} {{ data.item.lastName }}
              </v-list-tile-title>
            </v-list-tile-content>
          </template>

v-slot:item='data' -вместо данных можно использовать любое имя, которое вы хотите: v-slot:item="theItems" также будет работать (примечание: тогда вы будете использовать {{ theItems.item.firstName }}...

Причина, по которой вы должны использовать data.ITEM.x (имеется в виду ITEM)потому что это то, что Vuetify называет scoped slot для v-select - , подробнее об этом можно прочитать здесь .. Надеюсь, это поможет!

enter image description here


new Vue({
  el: "#app",
  props: {
    value: {
      type: [String, Object]
    }
  },
  data() {
    return {
      chosenItems: [],
      items: [{
          firstName: "John",
          lastName: "Smith",
          Age: 44
        },
        {
          firstName: "Sarah",
          lastName: "Martin",
          Age: 32
        },
        {
          firstName: "Derick",
          lastName: "Johnson",
          Age: 39
        },
        {
          firstName: "Mary",
          lastName: "Spitzer",
          Age: 22
        },
        {
          firstName: "Wendy",
          lastName: "Macdonald",
          Age: 57
        },
      ]
    };
  },
  computed: {
    selectedItems: {
      get() {
        return this.value;
      },
      set(item) {
        // Could either emit (so you can use v-model on the parent)
        // or add to array
        this.chosenItems.push(item)
        this.$emit("input", item);
      }
    }
  }
});
<link href="https://cdn.jsdelivr.net/npm/vuetify@1.5.6/dist/vuetify.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@1.5.6/dist/vuetify.min.js"></script>


<div id="app">
  <v-app>
    <v-content>
      <v-container>
        <v-layout row>
          <v-flex>
            <v-select 
              v-model='selectedItems' 
              label='Select One Or Many' 
              :items="items" 
              item-text="firstName" 
              chips 
              clearable 
              multiple 
              return-object
            >
              <template v-slot:selection='data'>
               <v-chip
                :key="JSON.stringify(data.item)"
                close
                class="chip--select-multi"
                @input="data.parent.selectItem(data.item)"
               >
                 {{ data.item.firstName }} {{ data.item.lastName }}
                </v-chip>
              </template>
              <template v-slot:item='data'>
                <v-list-tile-content>
                  <v-list-tile-title>
                    {{ data.item.firstName }} {{ data.item.lastName }}
                  </v-list-tile-title>
                </v-list-tile-content>
              </template>
            </v-select>
          </v-flex>
        </v-layout>
        <div class="mt-5">
          <v-layout>
            <v-flex>
              <h3>Chosen Items Will Be Displayed Here:</h3>
            </v-flex>
          </v-layout>
          <div v-for="(chosen, index) in chosenItems">
            <hr/>
            <div v-for="(eachChosen, i) in chosen">
              {{ eachChosen }}
            </div>
            <hr/><br/>
          </div>
        </div>
      </v-container>
    </v-content>
  </v-app>
</div>
...