簡體   English   中英

更新行時如何刷新Fabric-U的DetailsList

[英]How to refresh Fabric-Ui DetailsList when updating a row

我正在嘗試創建一個fabric-ui detailsList組件。 該組件應僅代表我在數據庫中擁有的內容,並可以為每行更新特定的列值。 要進行更新,每行應具有一個fabric-ui PrimaryButton。 我還在服務器中創建了兩個API(GET和POST)。 GET請求將把將顯示的所有資源返回到react應用程序,並且POST(在特定行的PrimaryButton上單擊時稱為POST)將在該行的ID中包含參數,並將更新該列的值。

我創建了一個根組件:App,它加載DetailsList並調用GET API以獲取所有資源並顯示它們。 我還創建了一個子組件:ResolveButton,它將在根組件的詳細信息列表中為每一行調用。

App.tsx:

import * as React from 'react';
import ResolveButton from './ResolveButton';


export interface IDetailsListCustomColumnsExampleState {
  sortedItems?: any[];
  columns?: IColumn[];
  hasError: boolean;
}


export class App extends React.Component<{}, IDetailsListCustomColumnsExampleState> {
  public constructor(props: {}) {
    super(props);

    this.state = {
      columns: [],
      hasError:false,
      sortedItems: []
    };
    this._renderItemColumn=this._renderItemColumn.bind(this);
    this.changeStatus = this.changeStatus.bind(this);
  }
  public componentDidCatch() {
    // Display fallback UI
    this.setState({ hasError: true });
  }
  public componentDidMount(){
    this.fetchResult()
  }
  public render() {
    const { sortedItems, columns } = this.state;
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>;
    }
    else{
      return (
        <DetailsList
          items={sortedItems as any[]}
          setKey="set"
          columns={columns}
          onRenderItemColumn={this._renderItemColumn}
          onColumnHeaderClick={this.onColumnClick}
          onItemInvoked={this._onItemInvoked}
          onColumnHeaderContextMenu={this._onColumnHeaderContextMenu}
          ariaLabelForSelectionColumn="Toggle selection"
          ariaLabelForSelectAllCheckbox="Toggle selection for all items"
        />
      );
    }

  }
  public changeStatus (itemId:React.ReactText){
    // TODO : call the POST API to update the status
    const { sortedItems } = this.state;
    const resolvedKey='Status';
    const idKey='Id';

    sortedItems!.map(ite => {
      if(ite[idKey] === itemId){
          ite[resolvedKey] = 3;
      }
      return ite;
    })
    this.setState({
      sortedItems
    });
  }
  private fetchResult = () =>{
    fetch('https://localhost:44329/home')
    .then((response) => response.json())
    .then(json => this.setState({ columns: _buildColumns(json),
    sortedItems: json })).catch((error) => 
    { 
      this.componentDidCatch()
    })
  }

  private onColumnClick = (event: React.MouseEvent<HTMLElement>, column: IColumn): void => {
    const { columns } = this.state;
    let { sortedItems } = this.state;
    let isSortedDescending = column.isSortedDescending;

    // If we've sorted this column, flip it.
    if (column.isSorted) {
      isSortedDescending = !isSortedDescending;
    }

    // Sort the items.
    sortedItems = sortedItems!.concat([]).sort((a, b) => {
      const firstValue = a[column.fieldName || ''];
      const secondValue = b[column.fieldName || ''];

      if (isSortedDescending) {
        return firstValue > secondValue ? -1 : 1;
      } else {
        return firstValue > secondValue ? 1 : -1;
      }
    });

    // Reset the items and columns to match the state.
    this.setState({
      columns: columns!.map(col => {
        col.isSorted = col.key === column.key;

        if (col.isSorted) {
          col.isSortedDescending = isSortedDescending;
        }

        return col;
      }),
      sortedItems      
    });
  };

  private _onColumnHeaderContextMenu(column: IColumn | undefined, ev: React.MouseEvent<HTMLElement> | undefined): void {

    alert(`column ${column!.key} contextmenu opened.`);
  }

  private _onItemInvoked(item: any, index: number | undefined): void {
    alert(`Item ${item.name} at index ${index} has been invoked.`);
  }

private _renderItemColumn(item: any, index: number, column: IColumn) {

  const fieldContent = item[column.fieldName || ''];

  const crisisColor = {
    1: 'Red',
    2: 'Orange',
    3: 'Yellow',
    4: 'Green'
  }
  const crisis = {
    1: 'Crise',
    2: 'Haute',
    3: 'Moyenne',
    4: 'Basse'
  }
  const statusColor = {
    1: 'Black',
    2: 'Black',
    3: 'Green'
  } 
  const status = {
    1: 'Ouvert',
    2: 'En cours',
    3: 'Résolu'
  }
  const resolvedKey='Status';
  const isResolved = item[resolvedKey]===3;
  switch (column.key) {
    case 'Status':
      return (
        <span data-selection-disabled={true} style={{ color: statusColor[fieldContent], height: '100%', display: 'block' }}>
          {status[fieldContent]}
        </span>
      );

    case 'Criticity':
      return (
        <span data-selection-disabled={true} style={{ color: crisisColor[fieldContent], height: '100%', display: 'block' }}>
          {crisis[fieldContent]}
        </span>
      );
    case 'Creator':
      return(
        <div>
        <img src="https://img.mobiscroll.com/demos/BMW_logo.png" width="30px" height="30px" style={{verticalAlign: 'middle', display:'inline' }}/>
        <p style={{verticalAlign: 'middle', display:'inline' , paddingLeft:'10px'}}>{fieldContent}</p>
        </div>
      ); 
    case 'AssignedTo':
      return(
        <div>
        <img src="https://img.mobiscroll.com/demos/BMW_logo.png" width="30px" height="30px" style={{verticalAlign: 'middle', display:'inline' }}/>
        <p style={{verticalAlign: 'middle', display:'inline' , paddingLeft:'10px'}}>{fieldContent}</p>
        </div>
      );

    case 'Id':
      return(
        // tslint:disable-next-line jsx-no-lambda
        <ResolveButton disabled={isResolved} uniqueId={fieldContent} changeStatus={ ()=>this.changeStatus(fieldContent)} /> 
      );

    default:
      return <span>{fieldContent}</span>;
  }
}
}
function _buildColumns(json:any[]) {
  const columns = buildColumns(json);
  return columns;
}

export default App;

ResolveButton.tsx

import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
import * as React from 'react';

export interface IHandleChange {
    changeStatus: ()=>void;
    disabled:boolean;
    uniqueId:string| number;
}
export class ResolveButton extends React.Component<IHandleChange, {}> {
    constructor(props:any) {

        super(props);
    }
    public render(): JSX.Element {
        return (
            <div>
                {
                    !this.props.disabled && 
                    <PrimaryButton
                        data-automation-id="test"
                        text="Résolu"
                        onClick={this.props.changeStatus}
                        allowDisabledFocus={true}
                    />
                }
            </div>
        );
    }
}
export default ResolveButton;

正如您在App.tsx中看到的那樣,當列鍵為“ Id”時,我將創建ResolveButton組件。 我的問題是,當單擊按鈕時,數據將在數據庫中更新,但是react應用程序中顯示的始終是數據庫的舊版本,因此我需要在調用POST API時刷新頁面。

這是一個反應類型的問題。

您的DetailList使用sortedItems來管理其狀態。 因此,當您單擊ResolveButton您需要更新狀態。 這沒有發生

要解決此問題, ResolveButton應該公開一個名為onResolved的屬性,以便主組件可以處理以更新其狀態。

class ResolveButton extends React.Component<IButtonProps, {}> {
  async handleClick() {
     const response = await fetch('https://localhost:44329/home')
     const json = await response.json();

     if (this.props.onResolved) {
         this.props.onResolved(json);
     }
  }
}

App只需調用onResolved即可更新狀態

class App extends React.Component<{}, IDetailsListCustomColumnsExampleState> {
  …
   <ResolveButton
        disabled={isResolved}
        uniqueId={fieldContent}
        onResolved={(data) => setState({'sortedItems': data})
   />
  …
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM