Skip to content

Commit

Permalink
feat(VForm): Add form level disabled prop
Browse files Browse the repository at this point in the history
A disabled VForm now disables all child inputs

fixes vuetifyjs#1707
  • Loading branch information
Logikgate committed Feb 19, 2020
1 parent c460b12 commit 5a4404a
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 24 deletions.
1 change: 1 addition & 0 deletions packages/docs/src/lang/en/components/Forms.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
}
},
"props": {
"disabled": "If enabled this will set all child inputs to disabled",
"lazyValidation": "If enabled, **value** will always be _true_ unless there are visible validation errors. You can still call `validate()` to manually trigger validation",
"value": "A boolean value representing the validity of the form."
},
Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/components/VCheckbox/VCheckbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default Selectable.extend({
// according to spec, should still show
// a color when disabled and active
validationState (): string | undefined {
if (this.disabled && !this.inputIndeterminate) return undefined
if (this.isDisabled && !this.inputIndeterminate) return undefined
if (this.hasError && this.shouldValidate) return 'error'
if (this.hasSuccess) return 'success'
if (this.hasColor !== null) return this.computedColor
Expand Down
14 changes: 14 additions & 0 deletions packages/vuetify/src/components/VForm/VForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export default mixins(
props: {
lazyValidation: Boolean,
value: Boolean,
disabled: Boolean,
},

data: () => ({
Expand All @@ -48,6 +49,14 @@ export default mixins(
deep: true,
immediate: true,
},
disabled: {
handler (val) {
this.$nextTick(() => {
this.propagateDisabledToInputs(val)
})
},
immediate: true,
},
},

methods: {
Expand Down Expand Up @@ -89,6 +98,11 @@ export default mixins(
this.inputs.forEach(input => input.reset())
this.resetErrorBag()
},
propagateDisabledToInputs (disabled: boolean): void {
this.inputs.forEach(input => {
input.formDisabled(disabled)
})
},
resetErrorBag () {
if (this.lazyValidation) {
// Account for timeout in validatable
Expand Down
21 changes: 20 additions & 1 deletion packages/vuetify/src/components/VForm/__tests__/VForm.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
Wrapper,
} from '@vue/test-utils'
import VTextField from '../../VTextField'
import VBtn from '../../VBtn'
import VForm from '../VForm'

const inputOne = Vue.component('input-one', {
Expand Down Expand Up @@ -244,4 +243,24 @@ describe('VForm.ts', () => {

expect(validate).toHaveBeenCalledTimes(2)
})

it('should disable all inputs', async () => {
const wrapper = mountFunction({
propsData: {
disabled: true,
},
slots: {
default: [VTextField],
},
})

await wrapper.vm.$nextTick()

let disabledInputs = 0
wrapper.vm.inputs.forEach(input => {
if (input.isDisabled) disabledInputs++
})

expect(disabledInputs).toBe(wrapper.vm.inputs.length)
})
})
11 changes: 8 additions & 3 deletions packages/vuetify/src/components/VInput/VInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export default baseMixins.extend<options>().extend({
return {
lazyValue: this.value,
hasMouseDown: false,
isFormDisabled: false,
}
},

Expand All @@ -71,7 +72,7 @@ export default baseMixins.extend<options>().extend({
'v-input--hide-details': !this.showDetails,
'v-input--is-label-active': this.isLabelActive,
'v-input--is-dirty': this.isDirty,
'v-input--is-disabled': this.disabled,
'v-input--is-disabled': this.isDisabled,
'v-input--is-focused': this.isFocused,
'v-input--is-loading': this.loading !== false && this.loading !== undefined,
'v-input--is-readonly': this.readonly,
Expand Down Expand Up @@ -107,6 +108,7 @@ export default baseMixins.extend<options>().extend({
return !!this.lazyValue
},
isDisabled (): boolean {
if (this.isFormDisabled) return true
return this.disabled || this.readonly
},
isLabelActive (): boolean {
Expand Down Expand Up @@ -150,6 +152,9 @@ export default baseMixins.extend<options>().extend({
this.genAppendSlot(),
]
},
formDisabled (disabled: boolean) {
this.isFormDisabled = disabled
},
genControl () {
return this.$createElement('div', {
staticClass: 'v-input__control',
Expand Down Expand Up @@ -178,7 +183,7 @@ export default baseMixins.extend<options>().extend({
'aria-label': hasListener ? kebabCase(type).split('-')[0] + ' icon' : undefined,
color: this.validationState,
dark: this.dark,
disabled: this.disabled,
disabled: this.isDisabled,
light: this.light,
},
on: !hasListener
Expand Down Expand Up @@ -230,7 +235,7 @@ export default baseMixins.extend<options>().extend({
props: {
color: this.validationState,
dark: this.dark,
disabled: this.disabled,
disabled: this.isDisabled,
focused: this.hasState,
for: this.computedId,
light: this.light,
Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/components/VRadioGroup/VRadio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export default baseMixins.extend<options>().extend({
return (this.radioGroup || {}).hasState
},
isDisabled (): boolean {
return this.disabled || !!(this.radioGroup || {}).disabled
return this.disabled || !!(this.radioGroup || {}).isDisabled
},
isReadonly (): boolean {
return this.readonly || !!(this.radioGroup || {}).readonly
Expand Down
6 changes: 3 additions & 3 deletions packages/vuetify/src/components/VSelect/VSelect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default baseMixins.extend<options>().extend({
/** @public */
activateMenu () {
if (
this.disabled ||
this.isDisabled ||
this.readonly ||
this.isMenuActive
) return
Expand Down Expand Up @@ -341,7 +341,7 @@ export default baseMixins.extend<options>().extend({
},
genChipSelection (item: object, index: number) {
const isDisabled = (
this.disabled ||
this.isDisabled ||
this.readonly ||
this.getDisabled(item)
)
Expand Down Expand Up @@ -371,7 +371,7 @@ export default baseMixins.extend<options>().extend({
genCommaSelection (item: object, index: number, last: boolean) {
const color = index === this.selectedIndex && this.computedColor
const isDisabled = (
this.disabled ||
this.isDisabled ||
this.getDisabled(item)
)

Expand Down
22 changes: 11 additions & 11 deletions packages/vuetify/src/components/VSlider/VSlider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ export default mixins<options &

const start = this.$vuetify.rtl ? 'auto' : '0'
const end = this.$vuetify.rtl ? '0' : 'auto'
const value = this.disabled ? `calc(${this.inputWidth}% - 10px)` : `${this.inputWidth}%`
const value = this.isDisabled ? `calc(${this.inputWidth}% - 10px)` : `${this.inputWidth}%`

return {
transition: this.trackTransition,
Expand All @@ -163,7 +163,7 @@ export default mixins<options &
const endDir = this.vertical ? 'height' : 'width'

const start = '0px'
const end = this.disabled ? `calc(${100 - this.inputWidth}% - 10px)` : `calc(${100 - this.inputWidth}%)`
const end = this.isDisabled ? `calc(${100 - this.inputWidth}% - 10px)` : `calc(${100 - this.inputWidth}%)`

return {
transition: this.trackTransition,
Expand All @@ -173,25 +173,25 @@ export default mixins<options &
},
showTicks (): boolean {
return this.tickLabels.length > 0 ||
!!(!this.disabled && this.stepNumeric && this.ticks)
!!(!this.isDisabled && this.stepNumeric && this.ticks)
},
numTicks (): number {
return Math.ceil((this.maxValue - this.minValue) / this.stepNumeric)
},
showThumbLabel (): boolean {
return !this.disabled && !!(
return !this.isDisabled && !!(
this.thumbLabel ||
this.$scopedSlots['thumb-label']
)
},
computedTrackColor (): string | undefined {
if (this.disabled) return undefined
if (this.isDisabled) return undefined
if (this.trackColor) return this.trackColor
if (this.isDark) return this.validationState
return this.validationState || 'primary lighten-3'
},
computedTrackFillColor (): string | undefined {
if (this.disabled) return undefined
if (this.isDisabled) return undefined
if (this.trackFillColor) return this.trackFillColor
return this.validationState || this.computedColor
},
Expand Down Expand Up @@ -250,7 +250,7 @@ export default mixins<options &
'v-slider--vertical': this.vertical,
'v-slider--focused': this.isFocused,
'v-slider--active': this.isActive,
'v-slider--disabled': this.disabled,
'v-slider--disabled': this.isDisabled,
'v-slider--readonly': this.readonly,
...this.themeClasses,
},
Expand Down Expand Up @@ -284,7 +284,7 @@ export default mixins<options &
attrs: {
value: this.internalValue,
id: this.computedId,
disabled: this.disabled,
disabled: this.isDisabled,
readonly: true,
tabindex: -1,
...this.$attrs,
Expand Down Expand Up @@ -380,7 +380,7 @@ export default mixins<options &
style: this.getThumbContainerStyles(valueWidth),
attrs: {
role: 'slider',
tabindex: this.disabled || this.readonly ? -1 : this.$attrs.tabindex ? this.$attrs.tabindex : 0,
tabindex: this.isDisabled || this.readonly ? -1 : this.$attrs.tabindex ? this.$attrs.tabindex : 0,
'aria-label': this.label,
'aria-valuemin': this.min,
'aria-valuemax': this.max,
Expand Down Expand Up @@ -486,7 +486,7 @@ export default mixins<options &
this.internalValue = value
},
onKeyDown (e: KeyboardEvent) {
if (this.disabled || this.readonly) return
if (this.isDisabled || this.readonly) return

const value = this.parseKeyDown(e, this.internalValue)

Expand Down Expand Up @@ -542,7 +542,7 @@ export default mixins<options &
return { value, isInsideTrack }
},
parseKeyDown (e: KeyboardEvent, value: number) {
if (this.disabled) return
if (this.isDisabled) return

const { pageup, pagedown, end, home, left, right, down, up } = keyCodes

Expand Down
2 changes: 1 addition & 1 deletion packages/vuetify/src/components/VSwitch/VSwitch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default Selectable.extend({
attrs (): object {
return {
'aria-checked': String(this.isActive),
'aria-disabled': String(this.disabled),
'aria-disabled': String(this.isDisabled),
role: 'switch',
}
},
Expand Down
6 changes: 3 additions & 3 deletions packages/vuetify/src/components/VTextField/VTextField.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ export default baseMixins.extend<options>().extend({
absolute: true,
color: this.validationState,
dark: this.dark,
disabled: this.disabled,
disabled: this.isDisabled,
focused: !this.isSingle && (this.isFocused || !!this.validationState),
for: this.computedId,
left: this.labelPosition.left,
Expand Down Expand Up @@ -376,7 +376,7 @@ export default baseMixins.extend<options>().extend({
attrs: {
...this.attrs$,
autofocus: this.autofocus,
disabled: this.disabled,
disabled: this.isDisabled,
id: this.computedId,
placeholder: this.placeholder,
readonly: this.readonly,
Expand Down Expand Up @@ -427,7 +427,7 @@ export default baseMixins.extend<options>().extend({
e && this.$nextTick(() => this.$emit('blur', e))
},
onClick () {
if (this.isFocused || this.disabled || !this.$refs.input) return
if (this.isFocused || this.isDisabled || !this.$refs.input) return

this.$refs.input.focus()
},
Expand Down

0 comments on commit 5a4404a

Please sign in to comment.