Skip to content

Commit

Permalink
fix(VCombobox): hide placeholder when dirty (#17122)
Browse files Browse the repository at this point in the history
fixes #16519
fixes #16493

Co-authored-by: Kael <kaelwd@gmail.com>
  • Loading branch information
johnleider and KaelWD authored Apr 12, 2023
1 parent 4a9eae2 commit 69ce260
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export const VAutocomplete = genericComponent<new <
useRender(() => {
const hasChips = !!(props.chips || slots.chip)
const hasList = !!((!props.hideNoData || displayItems.value.length) || slots.prepend || slots.append || slots['no-data'])
const isDirty = model.value.length > 0
const [textFieldProps] = VTextField.filterProps(props)

return (
Expand All @@ -268,7 +269,7 @@ export const VAutocomplete = genericComponent<new <
modelValue={ search.value }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
validationValue={ model.externalValue }
dirty={ model.value.length > 0 }
dirty={ isDirty }
onInput={ onInput }
class={[
'v-autocomplete',
Expand All @@ -281,6 +282,7 @@ export const VAutocomplete = genericComponent<new <
]}
appendInnerIcon={ props.menuIcon }
readonly={ props.readonly }
placeholder={ isDirty ? undefined : props.placeholder }
onClick:clear={ onClear }
onMousedown:control={ onMousedownControl }
onFocus={ () => isFocused.value = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,30 @@ describe('VAutocomplete', () => {
expect(selectedItems.value).equal(undefined)
})
})

it('should conditionally show placeholder', () => {
cy.mount(props => (
<VAutocomplete placeholder="Placeholder" { ...props } />
))
.get('.v-autocomplete input')
.should('have.attr', 'placeholder', 'Placeholder')
.setProps({ label: 'Label' })
.get('.v-autocomplete input')
.should('not.be.visible')
.get('.v-autocomplete input')
.focus()
.should('have.attr', 'placeholder', 'Placeholder')
.should('be.visible')
.blur()
.setProps({ persistentPlaceholder: true })
.get('.v-autocomplete input')
.should('have.attr', 'placeholder', 'Placeholder')
.should('be.visible')
.setProps({ modelValue: 'Foobar' })
.get('.v-autocomplete input')
.should('not.have.attr', 'placeholder')
.setProps({ multiple: true, modelValue: ['Foobar'] })
.get('.v-autocomplete input')
.should('not.have.attr', 'placeholder')
})
})
4 changes: 3 additions & 1 deletion packages/vuetify/src/components/VCombobox/VCombobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ export const VCombobox = genericComponent<new <
useRender(() => {
const hasChips = !!(props.chips || slots.chip)
const hasList = !!((!props.hideNoData || displayItems.value.length) || slots.prepend || slots.append || slots['no-data'])
const isDirty = model.value.length > 0
const [textFieldProps] = VTextField.filterProps(props)

return (
Expand All @@ -359,7 +360,7 @@ export const VCombobox = genericComponent<new <
v-model={ search.value }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
validationValue={ model.externalValue }
dirty={ model.value.length > 0 }
dirty={ isDirty }
class={[
'v-combobox',
{
Expand All @@ -371,6 +372,7 @@ export const VCombobox = genericComponent<new <
]}
appendInnerIcon={ props.items.length ? props.menuIcon : undefined }
readonly={ props.readonly }
placeholder={ isDirty ? undefined : props.placeholder }
onClick:clear={ onClear }
onMousedown:control={ onMousedownControl }
onFocus={ () => isFocused.value = true }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,30 @@ describe('VCombobox', () => {
cy.get('.v-combobox input')
.should('have.value', '0')
})

it('should conditionally show placeholder', () => {
cy.mount(props => (
<VCombobox placeholder="Placeholder" { ...props } />
))
.get('.v-combobox input')
.should('have.attr', 'placeholder', 'Placeholder')
.setProps({ label: 'Label' })
.get('.v-combobox input')
.should('not.be.visible')
.get('.v-combobox input')
.focus()
.should('have.attr', 'placeholder', 'Placeholder')
.should('be.visible')
.blur()
.setProps({ persistentPlaceholder: true })
.get('.v-combobox input')
.should('have.attr', 'placeholder', 'Placeholder')
.should('be.visible')
.setProps({ modelValue: 'Foobar' })
.get('.v-combobox input')
.should('not.have.attr', 'placeholder')
.setProps({ multiple: true, modelValue: ['Foobar'] })
.get('.v-combobox input')
.should('not.have.attr', 'placeholder')
})
})
1 change: 0 additions & 1 deletion packages/vuetify/src/components/VFileInput/VFileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ export const VFileInput = genericComponent<VFileInputSlots>()({
multiple: Boolean,
hint: String,
persistentHint: Boolean,
placeholder: String,
showSize: {
type: [Boolean, Number] as PropType<boolean | 1000 | 1024>,
default: false,
Expand Down
12 changes: 11 additions & 1 deletion packages/vuetify/src/components/VSelect/VSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ export const VSelect = genericComponent<new <
})
})
const selected = computed(() => selections.value.map(selection => selection.props.value))
const isFocused = ref(false)

let keyboardLookupPrefix = ''
let keyboardLookupLastTime: number
Expand Down Expand Up @@ -242,16 +243,24 @@ export const VSelect = genericComponent<new <
useRender(() => {
const hasChips = !!(props.chips || slots.chip)
const hasList = !!((!props.hideNoData || displayItems.value.length) || slots.prepend || slots.append || slots['no-data'])
const isDirty = model.value.length > 0
const [textFieldProps] = VTextField.filterProps(props)

const placeholder = isDirty || (
!isFocused.value &&
props.label &&
!props.persistentPlaceholder
) ? undefined : props.placeholder

return (
<VTextField
ref={ vTextFieldRef }
{ ...textFieldProps }
modelValue={ model.value.map(v => v.props.value).join(', ') }
onUpdate:modelValue={ v => { if (v == null) model.value = [] } }
v-model:focused={ isFocused.value }
validationValue={ model.externalValue }
dirty={ model.value.length > 0 }
dirty={ isDirty }
class={[
'v-select',
{
Expand All @@ -263,6 +272,7 @@ export const VSelect = genericComponent<new <
]}
appendInnerIcon={ props.menuIcon }
readonly
placeholder={ placeholder }
onClick:clear={ onClear }
onMousedown:control={ onMousedownControl }
onBlur={ onBlur }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,30 @@ describe('VSelect', () => {
.get('.v-select--active-menu').should('have.length', 0)
})

it('should conditionally show placeholder', () => {
cy.mount(props => (
<VSelect placeholder="Placeholder" { ...props } />
))
.get('.v-select input')
.should('have.attr', 'placeholder', 'Placeholder')
.setProps({ label: 'Label' })
.get('.v-select input')
.should('not.have.attr', 'placeholder')
.get('.v-select input')
.focus()
.should('have.attr', 'placeholder', 'Placeholder')
.blur()
.setProps({ persistentPlaceholder: true })
.get('.v-select input')
.should('have.attr', 'placeholder', 'Placeholder')
.setProps({ modelValue: 'Foobar' })
.get('.v-select input')
.should('not.have.attr', 'placeholder')
.setProps({ multiple: true, modelValue: ['Foobar'] })
.get('.v-select input')
.should('not.have.attr', 'placeholder')
})

describe('hide-selected', () => {
it('should hide selected item(s)', () => {
const items = ref(['Item 1',
Expand Down

0 comments on commit 69ce260

Please sign in to comment.