Vuetify: [Feature Request] Avatars in v-Select

Created on 31 May 2018  路  16Comments  路  Source: vuetifyjs/vuetify

Versions and Environment

Vuetify: 1.0.18
Vue: 2.5.16
Browsers: Chrome 66.0.3359.181
OS: Mac OS 10.13.4

Steps to reproduce

Create a v-select with a collection of items that contain an avatar property.

Expected Behavior

Avatars are rendered with each item in the select list and the selected item.

Actual Behavior

No avatars are rendered. Though I can see from debugging that v-select knows there is an avatar property and has properly set classes, props and flags.

Reproduction Link

https://codesandbox.io/s/7n1woo2w1

Other comments

I selected Vuetify version 1.0.18, but it also occurs on all version 1.1.0-x versions. I'm not sure about previous versions.
It appears that it simply is missing the v-list markup to render the avatar:

<v-list-tile-avatar>
  <img :src="item.avatar">
</v-list-tile-avatar>

before the <v-list-tile-content>

VSelect feature maybe

Most helpful comment

馃憤 for the feature request.

Here is how we are currently doing this (there may be a better way, but it is possible):

2018-06-07_11h30_33

<v-select
  class="elevation-0"
  label="Not being sorted"
  :items="employees"
  v-model="buy.sorter_id"
  item-text="full_name"
  item-value="id"
  dense
  solo
  clearable
  @input="handleSelectInput"
>
  <template slot="selection" slot-scope="data">
    <v-flex xs2>
      <v-avatar size="25px">
        <img :src="data.item.safe_avatar_url"/>
      </v-avatar>
    </v-flex>
    <v-flex class='ml-1'>
      {{ data.item.full_name }}
    </v-flex>
  </template>
  <template slot="item" slot-scope="data">
    <v-list-tile-avatar>
      <img :src="data.item.safe_avatar_url" />
    </v-list-tile-avatar>
    <v-list-tile-content>
      <v-list-tile-title v-html="data.item.full_name"></v-list-tile-title>
    </v-list-tile-content>
  </template>
</v-select>

All 16 comments

This is a feature request unless I'm mistaken in that this was never advertised functionality.

Oh, sorry @johnleider - I had gathered from the API doc on v-select (item-avatar - Set property of items鈥檚 avatar value) that it would render an Avatar like v-list does.

Understood. Originally the prop existed as a way to apply the avatar prop to the v-list-tile component. I'm undecided on baking it in, but can explore this in the future.

It's pretty pointless currently now that you can put a v-list-tile straight in the slot with whatever props you want. Although I guess it does simplify the markup a bit depending on what listeners and props you'd still need to attach.

That wasn't always a thing though.

馃憤 for the feature request.

Here is how we are currently doing this (there may be a better way, but it is possible):

2018-06-07_11h30_33

<v-select
  class="elevation-0"
  label="Not being sorted"
  :items="employees"
  v-model="buy.sorter_id"
  item-text="full_name"
  item-value="id"
  dense
  solo
  clearable
  @input="handleSelectInput"
>
  <template slot="selection" slot-scope="data">
    <v-flex xs2>
      <v-avatar size="25px">
        <img :src="data.item.safe_avatar_url"/>
      </v-avatar>
    </v-flex>
    <v-flex class='ml-1'>
      {{ data.item.full_name }}
    </v-flex>
  </template>
  <template slot="item" slot-scope="data">
    <v-list-tile-avatar>
      <img :src="data.item.safe_avatar_url" />
    </v-list-tile-avatar>
    <v-list-tile-content>
      <v-list-tile-title v-html="data.item.full_name"></v-list-tile-title>
    </v-list-tile-content>
  </template>
</v-select>

That is also the way I'm doing it too - using the scoped slots.

I'm actually reconsidering this: I submitted the "defect" issue because of the API documentation:
selects_input_components_ _vuetify_js

I had assumed that since item-disabled, item-text, and item-value worked that item-avatar would work too. However, as @KaelWD pointed out above, item-avatar is not really necessary when the slots are available. If it were added as a feature the first thing that's going to happen is that for someone, somewhere it won't render what they expect and there will be defects submitted and then there will need to be a bunch of props added for the avatar to be on the right, or left, the avatar size, alignment, etc... I could see all sorts of requests coming in for everyone's particular use case. Given that, it doesn't seem like such a good feature (and slots handle it already).

Having submitted this, I'd say after trying out the slots and the above comments, I would be perfectly happy if:

  • This issue is closed (do I close an issue I opened? It's probably up to the Vuetify dev team?)
  • The API documentation for item-avatar is removed (it doesn't do anything)
  • There was some guidance in the docs on rendering the selection slot so that it matches the normal selection. There is a good example already of using the scoped slots, but it uses chips in the selection slot.

I suspect the text in the selection slot needs to be styled with v-select__selection, but I'm not sure if that's all or appropriate. So an example or suggestion would resolve the problem I think.

Over all, I guess I'm saying teaching devs to use the slots rather then throwing a bunch of configuration props on the component is probably better.

I want to keep this open for a few reasons:

  1. I believe that it is important to offer sensible easy to use functionality that someone can just grab and go.
  2. For more advanced implementations, we offer slots

I'll evaluate this more as we get past v1.1 and move into v1.2 dev where we have to revisit a bunch of components due to the Material Design Spec update anyways.

I'm moving this to v2.0 as it will coincide nicely with the updates already in progress for v-list in regards to the new spec.

@johnleider are there any planned updates on this for Vuetify?

Using @jaxn is working but gets me an ESLint warning regarding the vue/valid-template-root (described as the template root requiring exactly one element).

As the rule points, that is not happening in the item slot where two elements are in the template root:

  <template slot="item" slot-scope="data">
    <v-list-tile-avatar>
      <img :src="data.item.safe_avatar_url" />
    </v-list-tile-avatar>
    <v-list-tile-content>
      <v-list-tile-title v-html="data.item.full_name"></v-list-tile-title>
    </v-list-tile-content>
  </template>

Using a div around any of these elements would pass the rule but just break the desired item display.

Any other workarounds suggested?

I could be wrong (I often am), but I'm not sure if we can resolve this without a breaking change which is why I pushed it to v2.0.

In regards to your question @IvoPereira , I'm not sure why you are getting that error, template slots can have as many elements as you want.

That should be reported on the eslint-plugin-vue repo

@johnleider that is probably the case @KaelWD referred.

The warning should not have an exception for template slots. I will make sure I get the issue there.

Will update this thread just in case someone finds an alternative approach or if I would get a fix for this situation in eslint-plugin-vue repo.

EDIT: Anyone that might want to be updated on the eslint vue issue, you may want to check it here.

@johnleider , @blalan05 ,

I'm also using the template 'selection' and 'item' slot approach with a v-autocomplete.

<template v-slot:selection="data">
    <v-avatar tile size="32" class="mr-2">
    <div
        class="flag-icon country-picker-icon"
        :class="{['flag-icon-' + data.item.value]: 1}"
    >&nbsp;</div>
    </v-avatar>
    <span class="country-picker-text" v-text="data.item.text"></span>
    &nbsp;
</template>
<template v-slot:item="data">
    <v-list-tile-avatar tile>
    <div
        class="flag-icon country-picker-icon"
        :class="{['flag-icon-' + data.item.value]: 1}"
    >&nbsp;</div>
    </v-list-tile-avatar>
    <v-list-tile-content>
    <v-list-tile-title v-html="data.item.text"></v-list-tile-title>
    </v-list-tile-content>
</template>

Behaviour wise the result is undesirable:
v-autocomplete_slots

From a behaviour perspective when searching the avatar should be hidden because it's context-sensitive, and the item-text should be editable (like it currently is when not using the 'selection' slot).

This is not currently possible because the input appended to the 'selection' slot doesn't contain the item-text.

In short, it would be ideal to be able to:

  1. Supply options (similar to menu-props) to the avatar e.g. size
  2. Hide the avatar when editing (keep spacing)
  3. Use a scoped slot to provide avatar content

Is it perhaps possible to use item-avatar to do the same?

@shelakel This seems like a feature request on the premise that avatars were already supported in the core of the component. The provided example is _your_ markup and would require you to make the appropriate changes to accommodate your needs.


As v-select is something I consider a trap component (there are an endless amount of features that could be useful and requested), I want to make sure that we make concise decisions when adding functionality and at the very least, provide an interface for users to implement their custom solutions.

With that being said, I have removed references to avatar properties for v2.0 but will explore this as a maybe implemented feature in the future. Thank you everyone for your responses and feedback on this issue.

Thank you for the Feature Request and interest in improving Vuetify. Unfortunately this is not functionality that we are looking to implement at this time.

If you have any additional questions, please reach out to us in our Discord community.

Was this page helpful?
0 / 5 - 0 ratings