Home Reference Source

src/components/checkbox/Checkbox.js

import Field from '../_classes/field/Field';

export default class CheckBoxComponent extends Field {
  static schema(...extend) {
    return Field.schema({
      type: 'checkbox',
      inputType: 'checkbox',
      label: 'Checkbox',
      key: 'checkbox',
      dataGridLabel: true,
      labelPosition: 'right',
      value: '',
      name: ''
    }, ...extend);
  }

  static get builderInfo() {
    return {
      title: 'Checkbox',
      group: 'basic',
      icon: 'check-square',
      documentation: '/userguide/#checkbox',
      weight: 50,
      schema: CheckBoxComponent.schema()
    };
  }

  get defaultSchema() {
    return CheckBoxComponent.schema();
  }

  get defaultValue() {
    const { name } = this.component;
    const defaultValue = super.defaultValue;

    return name ? (this.component[name] || this.emptyValue) : (defaultValue || this.component.defaultValue || false).toString() === 'true';
  }

  get labelClass() {
    let className = '';
    if (this.isInputComponent
      && !this.options.inputsOnly
      && this.component.validate
      && this.component.validate.required) {
      className += ' field-required';
    }
    return `${className}`;
  }

  get hasSetValue() {
    return this.hasValue();
  }

  get inputInfo() {
    const info = super.elementInfo();
    info.type = 'input';
    info.changeEvent = 'click';
    info.attr.type = this.component.inputType || 'checkbox';
    info.attr.class = 'form-check-input';
    if (this.component.name) {
      info.attr.name = `data[${this.component.name}]`;
    }
    info.attr.value = this.component.value ? this.component.value : 0;
    info.label = this.t(this.component.label, { _userInput: true });
    info.labelClass = this.labelClass;
    return info;
  }

  get labelInfo() {
    return {
      hidden: true
    };
  }

  render() {
    return super.render(this.renderTemplate('checkbox', {
      input: this.inputInfo,
      checked: this.checked,
      tooltip: this.interpolate(this.t(this.component.tooltip) || '', { _userInput: true }).replace(/(?:\r\n|\r|\n)/g, '<br />')
    }));
  }

  attach(element) {
    this.loadRefs(element, { input: 'multiple' });
    this.input = this.refs.input[0];
    if (this.refs.input) {
      this.addEventListener(this.input, this.inputInfo.changeEvent, () => this.updateValue(null, {
        modified: true
      }));
      this.addShortcut(this.input);
    }
    return super.attach(element);
  }

  detach(element) {
    if (element && this.input) {
      this.removeShortcut(this.input);
    }
    super.detach();
  }

  get emptyValue() {
    return this.component.inputType === 'radio' ? null : false;
  }

  isEmpty(value = this.dataValue) {
    return super.isEmpty(value) || value === false;
  }

  get key() {
    return this.component.name ? this.component.name : super.key;
  }

  getValueAt(index) {
    if (this.component.name) {
      return this.refs.input[index].checked ? this.component.value : '';
    }
    return !!this.refs.input[index].checked;
  }

  getValue() {
    const value = super.getValue();
    if (this.component.name) {
      return value ? this.setCheckedState(value) : this.setCheckedState(this.dataValue);
    }
    else {
      return (value === '') ? this.dataValue : !!value;
    }
  }

  get checked() {
    if (this.component.name) {
      return (this.dataValue === this.component.value);
    }
    return !!this.dataValue;
  }

  setCheckedState(value) {
    if (!this.input) {
      return;
    }
    if (this.component.name) {
      this.input.value = (value === this.component.value) ? this.component.value : 0;
      this.input.checked = (value === this.component.value && value !== this.dataValue) ? 1 : 0;
      value = value !== this.dataValue ? value : this.emptyValue;
    }
    else if (value === 'on') {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else if (value === 'off') {
      this.input.value = 0;
      this.input.checked = 0;
    }
    else if (value) {
      this.input.value = 1;
      this.input.checked = 1;
    }
    else {
      this.input.value = 0;
      this.input.checked = 0;
    }
    if (this.input.checked) {
      this.input.setAttribute('checked', true);
    }
    else {
      this.input.removeAttribute('checked');
    }
    return value;
  }

  setValue(value, flags = {}) {
    if (
      this.setCheckedState(value) !== undefined ||
      (!this.input && value !== undefined && (this.visible || !this.component.clearOnHide))
    ) {
      const changed = this.updateValue(value, flags);

      if (this.isHtmlRenderMode() && flags && flags.fromSubmission && changed) {
        this.redraw();
        return changed;
      }
    }
    return false;
  }

  getValueAsString(value) {
    return value ? 'Yes' : 'No';
  }

  updateValue(value, flags) {
    const changed = super.updateValue(value, flags);

    // Update attributes of the input element
    if (changed && this.input) {
      if (this.input.checked) {
        this.input.setAttribute('checked', 'true');
      }
      else {
        this.input.removeAttribute('checked');
      }
    }

    return changed;
  }
}