bootstrap-vue
Version:
Quickly integrate Bootstrap 4 components with Vue.js
166 lines (159 loc) • 5.18 kB
JavaScript
import { idMixin, formRadioCheckMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin } from '../../mixins'
import { isArray } from '../../utils/array'
import { looseEqual } from '../../utils'
export default {
mixins: [idMixin, formRadioCheckMixin, formMixin, formSizeMixin, formStateMixin, formCustomMixin],
render (h) {
const t = this
const input = h(
'input',
{
ref: 'check',
class: [t.is_ButtonMode ? '' : (t.is_Plain ? 'form-check-input' : 'custom-control-input'), t.get_StateClass],
directives: [
{ name: 'model', rawName: 'v-model', value: t.computedLocalChecked, expression: 'computedLocalChecked' }
],
attrs: {
id: t.safeId(),
type: 'checkbox',
name: t.get_Name,
disabled: t.is_Disabled,
required: t.is_Required,
autocomplete: 'off',
'true-value': t.value,
'false-value': t.uncheckedValue,
'aria-required': t.is_Required ? 'true' : null
},
domProps: { value: t.value, checked: t.is_Checked },
on: {
focus: t.handleFocus,
blur: t.handleFocus,
change: t.emitChange,
__c: (evt) => {
const $$a = t.computedLocalChecked
const $$el = evt.target
if (isArray($$a)) {
// Multiple checkbox
const $$v = t.value
let $$i = t._i($$a, $$v) // Vue's 'loose' Array.indexOf
if ($$el.checked) {
// Append value to array
$$i < 0 && (t.computedLocalChecked = $$a.concat([$$v]))
} else {
// Remove value from array
$$i > -1 && (t.computedLocalChecked = $$a.slice(0, $$i).concat($$a.slice($$i + 1)))
}
} else {
// Single checkbox
t.computedLocalChecked = $$el.checked ? t.value : t.uncheckedValue
}
}
}
}
)
let indicator = h(false)
if (!t.is_ButtonMode && !t.is_Plain) {
indicator = h('span', { class: 'custom-control-indicator', attrs: { 'aria-hidden': 'true' } })
}
const description = h(
'span',
{ class: t.is_ButtonMode ? null : (t.is_Plain ? 'form-check-description' : 'custom-control-description') },
[t.$slots.default]
)
const label = h(
'label',
{ class: [t.is_ButtonMode ? t.buttonClasses : t.is_Plain ? 'form-check-label' : t.labelClasses] },
[input, indicator, description]
)
if (t.is_Plain && !t.is_ButtonMode) {
return h('div', { class: ['form-check', { 'form-check-inline': !t.is_Stacked }] }, [label])
} else {
return label
}
},
props: {
value: {
default: true
},
uncheckedValue: {
// Not applicable in multi-check mode
default: false
},
indeterminate: {
// Not applicable in multi-check mode
type: Boolean,
default: false
}
},
computed: {
labelClasses () {
return [
'custom-control',
'custom-checkbox',
this.get_Size ? `form-control-${this.get_Size}` : '',
this.get_StateClass
]
},
is_Checked () {
const checked = this.computedLocalChecked
if (isArray(checked)) {
for (let i = 0; i < checked.length; i++) {
if (looseEqual(checked[i], this.value)) {
return true
}
}
return false
} else {
return looseEqual(checked, this.value)
}
}
},
watch: {
computedLocalChecked (newVal, oldVal) {
if (looseEqual(newVal, oldVal)) {
return
}
this.$emit('input', newVal)
this.$emit('update:indeterminate', this.$refs.check.indeterminate)
},
checked (newVal, oldVal) {
if (this.is_Child || looseEqual(newVal, oldVal)) {
return
}
this.computedLocalChecked = newVal
},
indeterminate (newVal, oldVal) {
this.setIndeterminate(newVal)
}
},
methods: {
emitChange ({ target: { checked } }) {
// Change event is only fired via user interaction
// And we only emit the value of this checkbox
if (this.is_Child || isArray(this.computedLocalChecked)) {
this.$emit('change', checked ? this.value : null)
if (this.is_Child) {
// If we are a child of form-checkbbox-group, emit change on parent
this.$parent.$emit('change', this.computedLocalChecked)
}
} else {
// Single radio mode supports unchecked value
this.$emit('change', checked ? this.value : this.uncheckedValue)
}
this.$emit('update:indeterminate', this.$refs.check.indeterminate)
},
setIndeterminate (state) {
// Indeterminate only supported in single checkbox mode
if (this.is_Child || isArray(this.computedLocalChecked)) {
return
}
this.$refs.check.indeterminate = state
// Emit update event to prop
this.$emit('update:indeterminate', this.$refs.check.indeterminate)
}
},
mounted () {
// Set initial indeterminate state
this.setIndeterminate(this.indeterminate)
}
}