|

   Veteran Tools Platform - Developer Documentation

There are no notes for this item.

PropRequired?TypeDefaultDescription
className No string
currentSort Yes {
  value: string,
  order: enum }
fields Yes [{
  label: string,
  value: string }]
data Yes [{
  id: union,
  values: [union],
  rowClass: string }]
onSort No func
<div id="reactMount" data-tpl="sortabletable">
    <table class="va-sortable-table va-table">
        <thead>
            <tr>
                <th><a role="button" tabindex="0">Label 1</a></th>
                <th><a role="button" tabindex="0">Label 2</a></th>
                <th><a role="button" tabindex="0">Label 3</a></th>
            </tr>
        </thead>
        <tbody>
            <tr class="class">
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr class="class">
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr class="class">
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
</div>
<script>
    window.currentProps = {
        "package": {
            "name": "department-of-veteran-affairs/jean-pants",
            "version": "0.1.0"
        },
        "assetPath": "/design-system/",
        "isProduction": true,
        "componentSourcePath": "SortableTable.jsx",
        "className": "va-table",
        "currentSort": {
            "value": "String",
            "order": "ASC"
        },
        "fields": [{
            "label": "Label 1",
            "value": "1"
        }, {
            "label": "Label 2",
            "value": "2"
        }, {
            "label": "Label 3",
            "value": "3"
        }],
        "data": [{
            "id": 1,
            "values": [1, 2, 3],
            "rowClass": "class"
        }, {
            "id": 2,
            "values": [1, 2, 3],
            "rowClass": "class"
        }, {
            "id": 3,
            "values": [1, 2, 3],
            "rowClass": "class"
        }]
    }
</script>
import React from 'react';
import SortableTable from './SortableTable';

export default function SortableTableExample(props) {
  return (
    <SortableTable
      {...props}>
    </SortableTable>
  );
}
package:
  name: department-of-veteran-affairs/jean-pants
  version: 0.1.0
assetPath: /design-system/
isProduction: true
componentSourcePath: SortableTable.jsx
className: va-table
currentSort:
  value: String
  order: ASC
fields:
  - label: Label 1
    value: '1'
  - label: Label 2
    value: '2'
  - label: Label 3
    value: '3'
data:
  - id: 1
    values:
      - 1
      - 2
      - 3
    rowClass: class
  - id: 2
    values:
      - 1
      - 2
      - 3
    rowClass: class
  - id: 3
    values:
      - 1
      - 2
      - 3
    rowClass: class
  • Content:
    import PropTypes from 'prop-types';
    import React from 'react';
    import classNames from 'classnames';
    
    class SortableTable extends React.Component {
      constructor(props) {
        super(props);
        this.makeHeader = this.makeHeader.bind(this);
        this.makeRow = this.makeRow.bind(this);
      }
    
      handleSort(value, order) {
        return () => this.props.onSort(value, order);
      }
    
      makeHeader(field) {
        if (field.nonSortable) {
          return (
            <th key={field.value}>
              {field.label}
            </th>
          );
        }
    
        // Determine what sort order the header will yield on the next click.
        // By default, clicking this header will sort in ascending order.
        // If it’s already ascending, next click will sort it in descending order.
        let nextSortOrder = 'ASC';
        let sortIcon;
    
        if (this.props.currentSort.value === field.value) {
          const iconClass = classNames({
            fa: true,
            'fa-caret-down': this.props.currentSort.order === 'DESC',
            'fa-caret-up': this.props.currentSort.order === 'ASC'
          });
    
          sortIcon = <i className={iconClass}></i>;
    
          if (this.props.currentSort.order === 'ASC') {
            nextSortOrder = 'DESC';
          }
        }
    
        return (
          <th key={field.value}>
            <a role="button" tabIndex="0" onClick={this.handleSort(field.value, nextSortOrder)}>
              {field.label}
              {sortIcon}
            </a>
          </th>
        );
      }
    
      makeRow(item) {
        const cells = this.props.fields.map(field => {
          return <td key={`${item.id}-${field.value}`}>{item[field.value]}</td>;
        });
        return <tr key={item.id} className={item.rowClass}>{cells}</tr>;
      }
    
      render() {
        const headers = this.props.fields.map(this.makeHeader);
        const rows = this.props.data.map(this.makeRow);
        const tableClass = classNames('va-sortable-table', this.props.className);
    
        return (
          <table className={tableClass}>
            <thead>
              <tr>
                {headers}
              </tr>
            </thead>
            <tbody>
              {rows}
            </tbody>
          </table>
        );
      }
    }
    
    SortableTable.propTypes = {
      className: PropTypes.string,
    
      // Field value to sort by in either ascending or descending order.
      // The `value` must be one of the values in the `fields` prop.
      currentSort: PropTypes.shape({
        value: PropTypes.string.isRequired,
        order: PropTypes.oneOf(['ASC', 'DESC'])
      }).isRequired,
    
      // Mappings of header labels to properties on the objects in `data`.
      fields: PropTypes.arrayOf(PropTypes.shape({
        label: PropTypes.string.isRequired,
        value: PropTypes.string.isRequired
      })).isRequired,
    
      // Each object represents data for a row.
      // An optional class may be provided to style specific rows.
      data: PropTypes.arrayOf(PropTypes.shape({
        id: PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string
        ]).isRequired,
        values: PropTypes.arrayOf(PropTypes.oneOfType([
          PropTypes.number,
          PropTypes.string])),
        rowClass: PropTypes.string
      })).isRequired,
    
      onSort: PropTypes.func
    };
    
    export default SortableTable;
    
  • URL: /components/raw/sortabletable/SortableTable.jsx
  • Filesystem Path: src/components/SortableTable/SortableTable.jsx
  • Size: 3.1 KB
  • Content:
    import React from 'react';
    import { shallow } from 'enzyme';
    import { expect } from 'chai';
    import { axeCheck } from '../../../lib/testing/helpers';
    import SortableTable from './SortableTable.jsx';
    
    /* Roll your own! */
    
    const fields = [{ label: 'Label 1', value: '1' }, { label: 'Label 2', value: '2' }, { label: 'Label 3', value: '3' }];
    const data = [{ id: 1, rowClass: 'class' }, { id: 2, rowClass: 'class' }, { id: 3, rowClass: 'class' }];
    const currentSort = { value: 'String', order: 'ASC' };
    
    describe('<SortableTable>', () => {
      it('should render', () => {
        const tree = shallow(<SortableTable fields={fields} data={data} currentSort={currentSort}/>);
        expect(tree.find('a').first().text()).to.contain('Label 1');
      });
    
      it('should pass aXe check', () => {
        return axeCheck(<SortableTable fields={fields} data={data} currentSort={currentSort}/>);
      });
    
    });
    
  • URL: /components/raw/sortabletable/SortableTable.unit.spec.jsx
  • Filesystem Path: src/components/SortableTable/SortableTable.unit.spec.jsx
  • Size: 879 Bytes