ulteam-react UlTable

UlTable component

Generate your table with controls from office-ui-fabric-react package. Configure table fields and component aggregates all rows values in one plain object. Table has edit mode, shimmer mode. You can fix header or/and fix left columns.

Demo

Try component on the demo

Sample

import { Icon } from 'office-ui-fabric-react/lib/components/Icon/Icon';
import * as React from 'react';
import { FormFields, INumberFieldProps, IUlTableRow } from '../../../..';
import { UlTable } from '../../../../form/components/UlTable/UlTable';
import { IFormField } from '../../../../form/data/Interfaces';
import { ITestTablePageState } from './ITestTablePageState';
import { UlTableSelectionMode } from '../../../../form/components/UlTable/UlTable.types';
import { Dropdown } from 'office-ui-fabric-react/lib/components/Dropdown/Dropdown';
import { IDropdownOption } from 'office-ui-fabric-react/lib/components/Dropdown/Dropdown.types';

export interface ITestTableRowFields {
  column1: string;
  column2: number;
  column3: number;
  column4: number;
  column5: string;
}

const defaultValues: ITestTableRowFields = {
  column1: 'default value',
  column2: 0,
  column3: 0,
  column4: 0,
  column5: ''
};

/**
 * Test table view
 */
export class TestTablePage extends React.Component<{}, ITestTablePageState> {
  private tableKey: number = 0;
  private testValue: string = 'Hello!';
  constructor(props: {}, state: ITestTablePageState) {
    super(props); 
    this.state = {
      selectionMode: UlTableSelectionMode.Multiple,
      tableRows: this.getDefaultTableRows()
    };
  }
  
  public shouldComponentUpdate(nextProps: {}, nextState: ITestTablePageState): boolean {
    return this.state.tableRows !== nextState.tableRows ||
      this.state.selectionMode !== nextState.selectionMode;
  }

  public render() {
    const selectionModeOptions: IDropdownOption[] = [
      {
        key: 'None',
        text: 'None'
      },
      {
        key: UlTableSelectionMode.Single,
        text: UlTableSelectionMode.Single
      },
      {
        key: UlTableSelectionMode.Multiple,
        text: UlTableSelectionMode.Multiple
      }
    ];

    return (
      <div>
        <Dropdown 
          label="Table selection mode"
          options={selectionModeOptions} 
          onChange={this.handleSelectionModeChange}
          defaultValue="None"
          style={ { width: 200 } }
        />
        <div className="form">
          <UlTable 
            key={this.tableKey}
            checkRequired={true}
            customClass="customTableClass"
            handleCellClick={this.handleCellClick}
            handleChangeValues={this.handleChangeFieldValues}
            handleRowClass={this.handleRowClass}
            onComponentMount={this.onComponentMount}
            onChangeSelection={this.onChangeSelection}
            readViewNoFocus={true}
            fields={this.getFormConfig(defaultValues)}
            rowCustomClass="customRowClass"
            rows={this.state.tableRows}
            selectionMode={this.state.selectionMode}
          />
        </div>
      </div>
    );
  }

  private getDefaultTableRows(): IUlTableRow<ITestTableRowFields>[] {
    let result: IUlTableRow<ITestTableRowFields>[] = [];

    for (let i = 0; i < 100; i++) {
      result.push({
        fieldValues: {
          column1: defaultValues.column1 + (i + 1).toString(),
          column2: defaultValues.column2 + Math.ceil(i + 1 / 10),
          column3: defaultValues.column3,
          column4: defaultValues.column4,
          column5: defaultValues.column5,
        },
        id: i,
        isReadView: i == 1 ? true : undefined
      });
    }

    return result;
  }

  public numberValidation = (config: IFormField<any>, newValue: any): string | undefined => {
    return isNaN(newValue) ? 
      'Value should be a number.' : 
      undefined;
  }

  public handleFormulaOnChangeColumn2 = (
    config: IFormField<INumberFieldProps>, 
    newValue: any, 
    prevValue: any, 
    prevFormFieldValues: ITestTableRowFields
    ): ITestTableRowFields => {
    
    let result: ITestTableRowFields = prevFormFieldValues;

    result.column2 = newValue;
    if (!isNaN(newValue)) {
      result.column3 = newValue * 2;
    }

    return result;
  }

  public handleSelectionModeChange = (
    event: React.FormEvent<HTMLDivElement>, 
    option?: IDropdownOption | undefined) => {

    const selectionMode = option && option.key !== 'None' ?
      option.key as UlTableSelectionMode :
      undefined;

    this.tableKey++;
    this.setState({ selectionMode });
  }

  public column3InnerHtml = (config: IFormField<any>, fieldValue?: any, formId?: number): JSX.Element => {
    let result: JSX.Element = <div></div>;

    if (formId && formId < 20) {
      result = (
        <div className="table-cell-comments">
          <Icon iconName="CaretTopRightSolid8"  
            onClick={() => {
              alert(formId);
              console.log(this.testValue);
            }} />
        </div>
      );
    }

    return result;
  }

  private getFormConfig(rowFields: ITestTableRowFields): IFormField<any>[] {
    return [
      FormFields.TextField('column1', {
        label: 'Column 1',
        customClass: 'class-column1',
        headerFieldProps: {
          isFiltering: true
        }
      }, {
        required: true,
        errorMessage: 'Error!!!'
      }),
      FormFields.NumberField('column2', {
        label: 'Column 2',
        customClass: 'class-column2',
        onChange: this.handleFormulaOnChangeColumn2,
        headerFieldProps: {
          customActions: [{
            key: 'CustomAction',
            text: 'Custom action',
            onClick: () => { alert(this.testValue )}
          }],
          isFiltering: true,
          isSorting: true
        },
        validationErrorOnChange: this.numberValidation
      }),
      FormFields.TextField('column3', {
        label: 'Formula',
        customClass: 'class-column3',
        maxWidth: 70,
        minWidth: 70,
        flexGrow: 0.5,
        innerHtml: this.column3InnerHtml
      }),
      FormFields.NumberField('column4', {
        label: 'Column 4',
        customClass: 'class-column4'
      }),
      FormFields.TextField('column5', {
        label: 'Column 5',
        customClass: 'customMultiline'
      }, {
        multiline: true,
        multilineAutoHeight: true,
        multilineResizable: true,
        multilineRows: 1
      })
    ];
  }

  private handleCellClick = (fieldId: string, fieldConfig: IFormField<any>, formId?: number, fieldValue?: any) => {
    console.log('handleCellClick', fieldConfig, fieldValue);
  }

  private handleChangeFieldValues = (rows: IUlTableRow<ITestTableRowFields>[]) => {
    console.log(rows);
  }

  private handleRowClass = (fieldValues: any, rowId: number, rowIndex: number, isTotalRow?: boolean | undefined): string => {
    return rowIndex % 2 === 0 ? 'handleRowClass' : '';
  } 

  private onComponentMount = (rows: IUlTableRow<ITestTableRowFields>[]) => {
    console.log('onComponentMount', rows);
  }

  private onChangeSelection = (selectedRows: number[]) => {
    console.log('selectedRows', selectedRows);
  }
}

IUlTableProps

Property Name Required Type Comments
addTotalRow Optional boolean Add total row on the bottom of the table. For handling add ‘handleTotalRow’ prop. WARN: it is working only for text and number field types
checkRequired   boolean Add error message if required value is empty
customClass Optional string Add custom class to main div
defaultRowFieldName Optional string Focus on the field by default
defaultRowId Optional number Focus on the row by default
errorsAsTooltip Optional boolean Error as Office UI Fabric Tooltip component
fieldNavByArrows Optional boolean Add cell navigation by keyboard arrows and enter buttons
fields   Array‹IFormField‹any›› Row fields configuration
fixHeight Optional number Table row
handleCellClick Optional function Click event on any cell in table
handleChangeValues   function Fires if any field (cell) value has changed
handleRowClass Optional function Add your class to row related on row data
handleTotalRow Optional function If you want to add total row in table, you should set property addTotalRow = true Set values for total row. WARN: it is working only for text and number field types
hideHeader Optional boolean Hide table header or not
isShimmer Optional boolean Show Office UI Shimmer component instead of field
onChangeSelection Optional function  
onComponentMount Optional function Get table metadata with error fields after mount Use this if you need to know info about error fields directly after mount component
readView Optional boolean Table on read mode
readViewNoFocus Optional boolean No focused rows will always be on read mode
rowCustomClass Optional string Add custom class to row div
rows   Array‹IUlTableRow‹any›› Table row values and errors
scrollOptions Optional IUlTableScrollOptions Add scroll to the table and fix header on the top
selectionMode Optional UlTableSelectionMode Controls how/if the details list manages selection. Options include single, multiple
shimmerRowCount Optional number  

Updated: