|

   Veteran Tools Platform - Developer Documentation

There are no notes for this item.

PropRequired?TypeDefaultDescription
checked No bool If the checkbox is checked or not
errorMessage No string Error message for the modal
name No string Name for the modal
label Yes union Label for the checkbox
onValueChange Yes func Handler for when the checkbox is changed
required No bool If the checkbox is required or not
<div id="reactMount" data-tpl="errorablecheckbox">
    <div class="form-checkbox usa-input-error"><input type="checkbox" autocomplete="false" aria-describedby="errorable-checkbox-28-error-message" id="errorable-checkbox-28" /><label class="usa-input-error-label" name="undefined-label" for="errorable-checkbox-28">Errorable Checkbox<span class="form-required-span">*</span></label>
        <span
            class="usa-input-error-message" role="alert" id="errorable-checkbox-28-error-message"><span class="sr-only">Error</span> Error message</span>
    </div>
</div>
<script>
    window.currentProps = {
        "package": {
            "name": "department-of-veteran-affairs/jean-pants",
            "version": "0.1.0"
        },
        "assetPath": "/design-system/",
        "isProduction": true,
        "componentSourcePath": "./ErrorableCheckbox.jsx",
        "id": "default",
        "errorMessage": "Error message",
        "label": "Errorable Checkbox",
        "required": true,
        "title": "ErrorableCheckbox"
    }
</script>
import React from 'react';
import ErrorableCheckbox from './ErrorableCheckbox';

export default function ErrorableCheckboxExample(props) {
  return (
    <ErrorableCheckbox
      label='Errorable Checkbox'
      onValueChange={(e) => {e.target.checked}}
      {...props}/>
  );
}
package:
  name: department-of-veteran-affairs/jean-pants
  version: 0.1.0
assetPath: /design-system/
isProduction: true
componentSourcePath: ./ErrorableCheckbox.jsx
id: default
errorMessage: Error message
label: Errorable Checkbox
required: true
title: ErrorableCheckbox
  • Content:
    import PropTypes from 'prop-types';
    import React from 'react';
    import _ from 'lodash';
    import ToolTip from '../../../Tooltip/Tooltip';
    
    /**
     * A form checkbox with a label that can display error messages.
     *
     * Validation has the following props.
     * `checked` - Boolean. Whether or not the checkbox is checked.
     * `errorMessage` - Error string to display in the component.
     *                  When defined, indicates checkbox has a validation error.
     * `label` - String for the checkbox label.
     * `name` - String for name attribute.
     * `toolTipText` - String with help text for user.
     * `tabIndex` - Number for keyboard tab order.
     * `onValueChange` - a function with this prototype: (newValue)
     * `required` - boolean. Render marker indicating field is required.
     */
    class ErrorableCheckbox extends React.Component {
      constructor() {
        super();
        this.handleChange = this.handleChange.bind(this);
      }
    
      componentWillMount() {
        this.inputId = _.uniqueId('errorable-checkbox-');
      }
    
      handleChange(domEvent) {
        this.props.onValueChange(domEvent.target.checked);
      }
    
      render() {
        // TODO: extract error logic into a utility function
        // Calculate error state.
        let errorSpan = '';
        let errorSpanId = undefined;
        if (this.props.errorMessage) {
          errorSpanId = `${this.inputId}-error-message`;
          errorSpan = (
            <span className="usa-input-error-message" role="alert" id={errorSpanId}>
              <span className="sr-only">Error</span> {this.props.errorMessage}
            </span>
          );
        }
    
        // Addes ToolTip if text is provided.
        let toolTip;
        if (this.props.toolTipText) {
          toolTip = (
            <ToolTip
              tabIndex={this.props.tabIndex}
              toolTipText={this.props.toolTipText}/>
          );
        }
    
        // Calculate required.
        let requiredSpan = undefined;
        if (this.props.required) {
          requiredSpan = <span className="form-required-span">*</span>;
        }
    
        let className = `form-checkbox${
          this.props.errorMessage ? ' usa-input-error' : ''
        }`;
        if (!_.isUndefined(this.props.className)) {
          className = `${className} ${this.props.className}`;
        }
    
        return (
          <div className={className}>
            <input
              autoComplete="false"
              aria-describedby={errorSpanId}
              checked={this.props.checked}
              id={this.inputId}
              name={this.props.name}
              type="checkbox"
              onChange={this.handleChange}/>
            <label
              className={
                this.props.errorMessage ? 'usa-input-error-label' : undefined
              }
              name={`${this.props.name}-label`}
              htmlFor={this.inputId}>
              {this.props.label}
              {requiredSpan}
            </label>
            {errorSpan}
            {toolTip}
          </div>
        );
      }
    }
    
    ErrorableCheckbox.propTypes = {
      /**
       * If the checkbox is checked or not
       */
      checked: PropTypes.bool,
      /**
       * Error message for the modal
       */
      errorMessage: PropTypes.string,
      /**
       * Name for the modal
       */
      name: PropTypes.string,
      /**
       * Label for the checkbox
       */
      label: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
      /**
       * Handler for when the checkbox is changed
       */
      onValueChange: PropTypes.func.isRequired,
      /**
       * If the checkbox is required or not
       */
      required: PropTypes.bool
    };
    
    export default ErrorableCheckbox;
    
  • URL: /components/raw/errorablecheckbox/ErrorableCheckbox.jsx
  • Filesystem Path: src/components/form/controls/ErrorableCheckbox/ErrorableCheckbox.jsx
  • Size: 3.4 KB
  • Content:
    import React from 'react';
    import { expect } from 'chai';
    import { shallow } from 'enzyme';
    import { axeCheck } from '../../../../../lib/testing/helpers';
    import ErrorableCheckbox from './ErrorableCheckbox.jsx';
    import sinon from 'sinon';
    
    describe('<ErrorableCheckbox/>', () => {
      it('should render', () => {
        const tree = shallow(
          <ErrorableCheckbox label="test" onValueChange={() => {}}/>
        );
        expect(tree.text()).to.contain('test');
      });
    
      it('should pass aXe check', () => {
        return axeCheck(
          <ErrorableCheckbox label="test" onValueChange={() => {}}/>
        );
      });
      it('ensure checked changes propagate', () => {
        const handleChangeSpy = sinon.spy(
          ErrorableCheckbox.prototype,
          'handleChange'
        );
        const tree = shallow(
          <ErrorableCheckbox label="test" onValueChange={() => {}}/>
        );
        const event = { target: { checked: true } };
    
        const checkBox = () => tree.find('[type="checkbox"]');
        checkBox().simulate('change', event);
        expect(handleChangeSpy.calledOnce).to.be.true;
      });
      it('no error styles when errorMessage undefined', () => {
        const tree = shallow(
          <ErrorableCheckbox label="my label" onValueChange={_update => {}}/>
        );
    
        // No error classes.
        expect(tree.children('.usa-input-error')).to.have.lengthOf(0);
        expect(tree.children('.usa-input-error-label')).to.have.lengthOf(0);
        expect(tree.children('.usa-input-error-message')).to.have.lengthOf(0);
    
        // Ensure no unnecessary class names on label w/o error..
        const labels = tree.children('label');
        expect(labels).to.have.lengthOf(1);
        expect(labels.prop('className')).to.be.equal(
          undefined,
          'Unnecessary class names on label without error'
        );
    
        // No error means no aria-describedby to not confuse screen readers.
        const inputs = tree.find('input');
        expect(inputs).to.have.lengthOf(1);
        expect(inputs.prop('aria-describedby')).to.be.equal(
          undefined,
          'Unnecessary aria-describedby'
        );
      });
    
      it('has error styles when errorMessage is set', () => {
        const tree = shallow(
          <ErrorableCheckbox
            label="my label"
            errorMessage="error message"
            onValueChange={_update => {}}/>
        );
    
        // Ensure all error classes set.
        expect(tree.find('.usa-input-error')).to.have.lengthOf(1);
    
        const labels = tree.find('.usa-input-error-label');
        expect(labels).to.have.lengthOf(1);
    
        const errorMessages = tree.find('.usa-input-error-message');
        expect(errorMessages).to.have.lengthOf(1);
        expect(errorMessages.text()).to.equal('Error error message');
    
        // No error means no aria-describedby to not confuse screen readers.
        const inputs = tree.find('input');
        expect(inputs).to.have.lengthOf(1);
        expect(inputs.prop('aria-describedby')).to.not.be.equal(undefined);
        expect(inputs.prop('aria-describedby')).to.equal(errorMessages.prop('id'));
      });
    
      it('required=false does not have required asterisk', () => {
        const tree = shallow(
          <ErrorableCheckbox label="my label" onValueChange={_update => {}}/>
        );
    
        expect(tree.find('label').text()).to.equal('my label');
      });
    
      it('required=true has required asterisk', () => {
        const tree = shallow(
          <ErrorableCheckbox
            label="my label"
            required
            onValueChange={_update => {}}/>
        );
    
        const label = tree.find('label');
        expect(label.text()).to.equal('my label*');
      });
    
      it('label attribute propagates', () => {
        const tree = shallow(
          <ErrorableCheckbox label="my label" onValueChange={_update => {}}/>
        );
    
        // Ensure label text is correct.
        const labels = tree.find('label');
        expect(labels).to.have.lengthOf(1);
        expect(labels.text()).to.equal('my label');
    
        // Ensure label htmlFor is attached to input id.
        const inputs = tree.find('input');
        expect(inputs).to.have.lengthOf(1);
        expect(inputs.prop('id')).to.not.be.equal(undefined);
        expect(inputs.prop('id')).to.equal(labels.prop('htmlFor'));
      });
    });
    
  • URL: /components/raw/errorablecheckbox/ErrorableCheckbox.unit.spec.jsx
  • Filesystem Path: src/components/form/controls/ErrorableCheckbox/ErrorableCheckbox.unit.spec.jsx
  • Size: 4 KB
  • Handle: @errorablecheckbox
  • Preview:
  • Filesystem Path: src/components/form/controls/ErrorableCheckbox/ErrorableCheckbox.njk