Search code examples
reactjsfluent-uifluentui-react

fluent ui details List implementation in Functional component


Can anybody send code on how to implement fluent UI details List in Functional Component(https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/basic) and how to fetch data from API to details List


Solution

  • That's a start you will need to "refact" this code by the way this is a really good practice :

    import * as React from "react";
    import { Announced } from "office-ui-fabric-react/lib/Announced";
    import {
      TextField,
      ITextFieldStyles
    } from "office-ui-fabric-react/lib/TextField";
    import {
      DetailsList,
      DetailsListLayoutMode,
      Selection,
      IColumn
    } from "office-ui-fabric-react/lib/DetailsList";
    import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
    import { Fabric } from "office-ui-fabric-react/lib/Fabric";
    import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
    import { Text } from "office-ui-fabric-react/lib/Text";
    
    const exampleChildClass = mergeStyles({
      display: "block",
      marginBottom: "10px"
    });
    
    const textFieldStyles: Partial<ITextFieldStyles> = {
      root: { maxWidth: "300px" }
    };
    
    export interface IDetailsListBasicExampleItem {
      key: number;
      name: string;
      value: number;
    }
    
    export interface IDetailsListBasicExampleState {
      items: IDetailsListBasicExampleItem[];
      selectionDetails: string;
    }
    
    export const DetailsListBasicExampleFunction: React.FunctionComponent<
      {} | IDetailsListBasicExampleState
    > = () => {
      const _allItems: IDetailsListBasicExampleItem[] = [];
      const [selection, setSelection] = React.useState<Selection | undefined>();
      function _getSelectionDetails(): string {
        const selectionCount = selection ? selection.getSelectedCount() : 0;
    
        switch (selectionCount) {
          case 0:
            return "No items selected";
          case 1:
            return (
              "1 item selected: " +
              (selection.getSelection()[0] as IDetailsListBasicExampleItem).name
            );
          default:
            return `${selectionCount} items selected`;
        }
      }
      const [state, setState] = React.useState({
        items: _allItems,
        selectionDetails: _getSelectionDetails()
      });
      React.useEffect(() => {
        const _selection: Selection = new Selection({
          onSelectionChanged: () =>
            setState((prev) => {
              return { ...prev, selectionDetails: _getSelectionDetails() };
            })
        });
        setSelection(_selection);
        for (let i = 0; i < 200; i++) {
          _allItems.push({
            key: i,
            name: "Item " + i,
            value: i
          });
        }
        setState((prev) => {
          return { ...prev, items: _allItems };
        });
      }, []);
      const _columns: IColumn[] = [
        {
          key: "column1",
          name: "Name",
          fieldName: "name",
          minWidth: 100,
          maxWidth: 200,
          isResizable: true
        },
        {
          key: "column2",
          name: "Value",
          fieldName: "value",
          minWidth: 100,
          maxWidth: 200,
          isResizable: true
        }
      ];
    
      // Populate with items for demos.
    
      const _onFilter = (
        ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
        text: string
      ): void => {
        console.log(text);
        setState((prev) => {
          return {
            ...prev,
            items: text
              ? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
              : _allItems
          };
        });
      };
    
      const _onItemInvoked = (item: IDetailsListBasicExampleItem): void => {
        alert(`Item invoked: ${item.name}`);
      };
      return selection ? (
        <Fabric>
          <div className={exampleChildClass}>{state.selectionDetails}</div>
          <Text>
            Note: While focusing a row, pressing enter or double clicking will
            execute onItemInvoked, which in this example will show an alert.
          </Text>
          <Announced message={state.selectionDetails} />
          <TextField
            className={exampleChildClass}
            label="Filter by name:"
            onChange={(e, t) => _onFilter(e, t ?? "")}
            styles={textFieldStyles}
          />
          <Announced
            message={`Number of items after filter applied: ${state.items.length}.`}
          />
          <MarqueeSelection selection={selection}>
            <DetailsList
              items={state.items}
              columns={_columns}
              setKey="set"
              layoutMode={DetailsListLayoutMode.justified}
              selection={selection}
              selectionPreservedOnEmptyClick={true}
              ariaLabelForSelectionColumn="Toggle selection"
              ariaLabelForSelectAllCheckbox="Toggle selection for all items"
              checkButtonAriaLabel="select row"
              onItemInvoked={_onItemInvoked}
            />
          </MarqueeSelection>
        </Fabric>
      ) : (
        <div>Loading</div>
      );
    };
    
    

    Edit clever-germain-t476s
    UPDATE
    To pass this sample of code in JSX this is pretty easy you just need to remove all type thing.
    And to fetch data I use axios.
    see the code below:

    import * as React from "react";
    import { Announced } from "office-ui-fabric-react/lib/Announced";
    import { TextField } from "office-ui-fabric-react/lib/TextField";
    import {
      DetailsList,
      DetailsListLayoutMode,
      Selection
    } from "office-ui-fabric-react/lib/DetailsList";
    import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
    import { Fabric } from "office-ui-fabric-react/lib/Fabric";
    import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
    import { Text } from "office-ui-fabric-react/lib/Text";
    import axios from "axios";
    const exampleChildClass = mergeStyles({
      display: "block",
      marginBottom: "10px"
    });
    
    const textFieldStyles = {
      root: { maxWidth: "300px" }
    };
    
    export const DetailsListBasicExampleFunction = () => {
      const _allItems = [];
      const [selection, setSelection] = React.useState();
      function _getSelectionDetails() {
        const selectionCount = selection ? selection.getSelectedCount() : 0;
    
        switch (selectionCount) {
          case 0:
            return "No items selected";
          case 1:
            return "1 item selected: " + selection.getSelection()[0].name;
          default:
            return `${selectionCount} items selected`;
        }
      }
      const [state, setState] = React.useState({
        items: _allItems,
        selectionDetails: _getSelectionDetails()
      });
      React.useEffect(() => {
        const _selection = new Selection({
          onSelectionChanged: () =>
            setState((prev) => {
              return { ...prev, selectionDetails: _getSelectionDetails() };
            })
        });
        setSelection(_selection);
        //********************** */fetch data from api***************************************
        axios
          .get("/data.json") //pass your url in param
          .then((res) =>
            setState((prev) => {
              return { ...prev, items: res.data };
            })
          ); //pass data in setState
      }, []);
      const _columns = [
        {
          key: "column1",
          name: "Name",
          fieldName: "name",
          minWidth: 100,
          maxWidth: 200,
          isResizable: true
        },
        {
          key: "column2",
          name: "Value",
          fieldName: "value",
          minWidth: 100,
          maxWidth: 200,
          isResizable: true
        }
      ];
    
      // Populate with items for demos.
    
      const _onFilter = (ev, text) => {
        console.log(text);
        setState((prev) => {
          return {
            ...prev,
            items: text
              ? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
              : _allItems
          };
        });
      };
    
      const _onItemInvoked = (item) => {
        alert(`Item invoked: ${item.name}`);
      };
      return selection ? (
        <Fabric>
          <div className={exampleChildClass}>{state.selectionDetails}</div>
          <Text>
            Note: While focusing a row, pressing enter or double clicking will
            execute onItemInvoked, which in this example will show an alert.
          </Text>
          <Announced message={state.selectionDetails} />
          <TextField
            className={exampleChildClass}
            label="Filter by name:"
            onChange={(e, t) => _onFilter(e, t ?? "")}
            styles={textFieldStyles}
          />
          <Announced
            message={`Number of items after filter applied: ${state.items.length}.`}
          />
          <MarqueeSelection selection={selection}>
            <DetailsList
              items={state.items}
              columns={_columns}
              setKey="set"
              layoutMode={DetailsListLayoutMode.justified}
              selection={selection}
              selectionPreservedOnEmptyClick={true}
              ariaLabelForSelectionColumn="Toggle selection"
              ariaLabelForSelectAllCheckbox="Toggle selection for all items"
              checkButtonAriaLabel="select row"
              onItemInvoked={_onItemInvoked}
            />
          </MarqueeSelection>
        </Fabric>
      ) : (
        <div>Loading</div>
      );
    };
    
    

    Edit festive-bhabha-jtj65