vuetify icon indicating copy to clipboard operation
vuetify copied to clipboard

[Feature Request] Improve v-select mobile UX

Open birdlavv opened this issue 6 years ago • 11 comments

Problem to solve

The current material v-select dropdown often has trouble on mobile devices when there are many options, especially when a fullscreen modal/dialog is involved. Using a browser's default select can improve UX for mobile devices. For example iPhone Safari provides its own selection dial for HTML <select/ > that is better equipped for managing many <option/ >s on smaller devices.

Proposed solution

https://codesandbox.io/s/zq4lo037wl

is the implementation we’ve been using as a placeholder at work to offer this functionality.

birdlavv avatar May 15 '18 02:05 birdlavv

We have considered rendering a v-dialog instead of a v-menu on mobile devices. I don't think we'd bother with a native select as most of the features wouldn't work any more. I also don't really want to add another prop to the component, it already has like 70.

KaelWD avatar May 16 '18 08:05 KaelWD

I am expecting the behavior. I would like to have this feature also. Another important point is if you are submitting forms using the default browser submit the text of the select always get submitted instead of the value. This makes the default browser submission to be broken. I am using jQuery.AjaxForm for form submissions which have worked for me for years so I can support ajax file uploads even is browser doesn't support it. There is no way to get the value using the default submit, the only way is via JavaScript on the Vue event and manually setup the ajax request. We just need to add an option like native = true and render it using the default browser select tag. Please make this possible we really need this to support browser default submission.

arivera12 avatar May 27 '18 15:05 arivera12

Sounds like you want #838, which was implemented for all inputs in v1.1. This issue is about UX, not how data is handled.

so I can support ajax file uploads even is browser doesn't support it.

That doesn't even make sense, if a browser is so old that it doesn't support ajax then it definitely won't work with vuetify.

KaelWD avatar May 27 '18 16:05 KaelWD

@KaelWD the point of using old browsers is not a problem if you are using the plugin I mentioned above. If browser doesn't support Ajax file upload this plugin uses an iframe on the fly and submits it for you. I have used this plugin over long years. The thing is about maintenance of the applications. Submitting a form is better rather than manually managing an Ajax request, you just simply need to write extract code for it when browser automatically manage it for you. Imagine a huge form like 30 inputs you will need to write a huge ajax code with the props and data for it. I don't get the point uploading data manually when you have an option to submit it using ajax or uploading files use the File API if browser supports it. Do you understand my point? Do you have used this plugin I mentioned? There is nothing more easier than this plugin to submit & manage forms. Simple as that.

arivera12 avatar May 28 '18 02:05 arivera12

File API if browser supports it

https://caniuse.com/#search=FormData

you will need to write a huge ajax code with the props and data for it

<template>
  <v-form>
    <v-text-field v-model="form.first"/>
    <v-text-field v-model="form.last"/>
    <v-text-field v-model="form.email"/>
    ...
  </v-form>
</template>

<script>
  import axios from 'axios'
  export default {
    data: () => ({
      form: {
        first: '',
        last: '',
        email: '',
        ...
      }
    }),
    methods: {
      submit () {
        axios.post('/backend', this.form).then(...)
      }
    }
  }
</script>

Wow, so huge. You could even just have <v-text-field v-for="input in form" v-model="form[input]"/> if you aren't doing anything complex.

Do you have used this plugin I mentioned?

No. jquery is cancer. We do support native form submission in 1.1 because people asked for it, and if it isn't working correctly then you should open a bug report with a minimal reproduction.

KaelWD avatar May 28 '18 05:05 KaelWD

@KaelWD I develop government applications and they use old versions of internet explorer (9-11) that's why I stick with this, I can't just said to them we do not support IE old versions because everything is regulated by them and it must works with the software and hardware they own, simple as that. I only use jquery-ajax-only as my ajax client combined with jquery.ajaxForm so I don't have issues with IE older versions. Do you understand my case now?

arivera12 avatar May 28 '18 14:05 arivera12

Not really, we don't support anything older than IE11 (and even then is a bit shoddy). But if you want to use vuetify for that then go ahead. And as I said before, open a new issue if the internal input is not getting the correct data, it's supposed to be supported now in v1.1.

KaelWD avatar May 28 '18 16:05 KaelWD

@KaelWD Has any more thought been given to this? Having a native select option is really important for a couple of reasons.

  1. The current component does not reliably accept values from a browser autofill, particularly on mobile. For example, if I have an address form that uses the select component for the state or province field, if the user starts typing in one of the first fields in the form, the browser will offer to autocomplete the form with one of their previously used addresses. When the address is selected, all of the fields get populated except for the select because the select doesn’t contain a real visible input to be filled in. Currently I have to create hidden fields to accept these auto filled values, and bind the select components value to it, but this does not work reliably on all browsers since some mobile browsers do not appear to fill in visually hidden inputs.

  2. Specifically on an iPhone, the select component is not recognized as a form input when using the native arrows above the keyboard to navigate through the fields of a form. The select gets skipped.

I am using vuetify in our e-commerce checkout. You can see it live on StoreYourBoard.com. Making the forms as easy as possible to use is extremely important in this type of use case. These limitations on the select component makes it very difficult to optimize the forms.

Here is an example of a material component with a native option to address these issues:

https://material-ui.com/components/selects/

Vuetify needs the same option in my opinion. What do you think?

flyingL123 avatar May 14 '20 03:05 flyingL123

@KaelWD any thoughts?

flyingL123 avatar May 18 '20 13:05 flyingL123

In case it helps anybody, I was able to create a NativeSelect component by extending the VTextField component and overriding the genInput() method to create a select rather than an input. I'm sure there is a better more future proof way to do this, but so far for me it's working great. This is the content of my NativeSelect.vue file:

<script>
import { VTextField } from 'vuetify/lib';

export default {
  extends: VTextField,

  props: {
    items: {
      type: Array,
      required: true,
    },
    appendOuterIcon: {
      type: String,
      default: '$dropdown',
    },
  },

  methods: {
    genInput() {
      const listeners = Object.assign({}, this.listeners$)
      delete listeners['change'] // Change should not be bound externally

      return this.$createElement('select', {
        style: {},
        domProps: {
          value: this.lazyValue,
        },
        attrs: {
          ...this.attrs$,
          autofocus: this.autofocus,
          disabled: this.disabled,
          id: this.computedId,
          readonly: this.readonly,
        },
        on: Object.assign(listeners, {
          blur: this.onBlur,
          input: this.onInput,
          focus: this.onFocus,
          keydown: this.onKeyDown,
        }),
        ref: 'input',
      }, this.genOptions());
    },

    genOptions() {
      return this.items.map(item => {
        return this.$createElement('option', {
          domProps: {
            innerHTML: item.name,
            value: item.code,
          }
        });
      });
    }
  }
}
</script>

<style scoped>
  select {
    position: absolute;
    z-index: 1;
    width: 100%;
    height: 100%;
    color: rgba(0,0,0,.87);
    cursor: pointer;
  }

  select:focus {
    outline: none;
  }

  >>> .v-input__append-outer {
    position: absolute;
    right: 11px;
  }
</style>

Then I use it in other .vue files like this:

<NativeSelect
  label="Country"
  outlined
  v-model="countryCode"
  :items="countries"
  name="country"
  autocomplete="country"
/>

In my case items is an array of country objects, each with a code and a name, which is why those keys are hardcoded into the genOptions method. This can of course be customized via props but I don't have a need for that yet.

flyingL123 avatar May 20 '20 01:05 flyingL123

Quasar has something very similar.

  • https://quasar.dev/vue-components/select#options-list-display-mode
  • https://codepen.io/pen?&editors=101

dixhuit avatar Oct 31 '22 18:10 dixhuit