在React Griddle中选择一行,并更改其背景颜色



我只是想知道是否有人已经能够改变一行的颜色,在React Griddle中,通过点击它(只有一次)。

我正在用JQuery做实验,甚至用Griddle Metadata,但它可能会以更干净的方式完成?

编辑:我使用React 15, Griddle内部MantraJS/Meteor,在我的React组件中使用Mantra容器获取数据。

我可以通过使用onClick事件获得数据,但不能在onClick事件中切换背景颜色,或者使用元数据。

谢谢!编辑:我使用另一个视图来显示表格的内容,所以现在我不需要改变我的表格单元格的背景,但如果我找到一个解决方案,我会完成这篇文章

你可以使用react-griddle props rowMetadataonRowClick来做到这一点:

class ComponentWithGriddle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedRowId: 0,
    };
  }
  onRowClick(row) {
    this.setState({ selectedRowId: row.props.data.id });
  }
  render() {
    const rowMetadata = {
      bodyCssClassName: rowData => (rowData.id === this.state.selectedRowId ? 'selected' : ''),
    };
    return (
      <Griddle
        ...
        rowMetadata={rowMetadata}
        onRowClick={this.onRowClick.bind(this)}
      />
    );
  }
}

现在这将selected类添加到所选的<tr>元素,所以你可以使用自定义样式来添加颜色或任何你想要应用于所选行的样式。

请注意,在Griddle Github问题中已经调用了一个更方便的API来选择行。

不知什么原因,我根本无法理解维斯基的答案。我想在过去的两年里,格莱德一定发生了一些变化。看起来目前在网络上流行的建议是"实现行选择作为一个插件",但我找不到任何例子。在对GitHub上的Position插件的TableEnhancer的代码进行了长时间的仔细研究和一堆试验和错误之后,我最终设法在TypeScript中为Griddle拼凑了以下行选择插件:

import * as React from "react";
import * as Redux from "redux";
import Griddle, { connect, GriddlePlugin, components } from "griddle-react";
export type RowId = string | number;
export type RowClickHandler = (event: React.MouseEvent<Element>, rowId: RowId) => void;
export type RowIdGetter<TData> = (rowData: TData) => RowId;
export interface IRowEnhancerProps {
    rowClickHandler: RowClickHandler;
    rowId: RowId;
    isSelected: boolean;
}
export class RowSelector<TData> {
    private _rowClickHandler: RowClickHandler = null;
    private _rowIdGetter: RowIdGetter<TData>;
    constructor(rowClickHandler: RowClickHandler, rowIdGetter: (rowData: TData) => RowId) {
        this._rowClickHandler = rowClickHandler;
        this._rowIdGetter = rowIdGetter;
    }
    public rowIdToSelect: RowId;
    public plugin: GriddlePlugin = {
        components: {
            RowEnhancer: (OriginalComponent: React.ComponentClass<components.RowProps>) =>
                this.rowSelectionEnhancer(OriginalComponent)
        }
    }
    private rowSelectionEnhancer(
        OriginalComponent: React.ComponentClass<components.RowProps>
        ): React.ComponentClass<components.RowProps> {
        const rowDataSelector = (state, { griddleKey }) => {
            return state
                .get('data')
                .find(rowMap => rowMap.get('griddleKey') === griddleKey)
                .toJSON();
        };
        return Redux.compose(
            connect((state, props) => {
                const rowData: TData = rowDataSelector(state, props as { griddleKey });
                const rowId: RowId = this._rowIdGetter(rowData);
                return {
                    ...props,
                    rowClickHandler: this._rowClickHandler,
                    rowId: rowId,
                    isSelected: rowId.toString() === this.rowIdToSelect.toString()
                };
            })
        )(class extends React.Component<IRowEnhancerProps, any>{
            public render() {
                return (
                    <OriginalComponent
                        {...this.props}
                        onClick={(event) => this.props.rowClickHandler(event, this.props.rowId)}
                        className={this.props.isSelected ? "selected" : ""}
                    />
                );
            }
        });
    }
}

这里是一个组件如何使用它的大致轮廓。(注意,我必须有选择地从一个更大更复杂的组件中提取这个例子,所以可能会有一些错误/不一致;很抱歉。它仍然应该给出一个很好的方法的总体概念。)

import * as React from "react";
import Griddle, { RowDefinition, plugins, GriddlePlugin} from "griddle-react";
import * as MyGriddlePlugins from "../GriddlePlugins";
export interface IPartInfo {
    serialNumber: number,
    name: string,
    location: string
}
export interface IPartListProps{
    parts: IPartInfo[],
    selectedSerialNumber: number
}
export class PartList extends React.Component<IPartListProps, void > {
    private rowSelector: MyGriddlePlugins.RowSelector<IPartInfo>;
    private rowIdGetter: MyGriddlePlugins.RowIdGetter<IPartInfo>;
    constructor(props?: IPartListProps, context?: any) {
        super(props, context);
        this._rowClickHandler = this._rowClickHandler.bind(this);
        this.rowSelector = new MyGriddlePlugins.RowSelector(
            this._rowClickHandler, 
            this._rowIdGetter);
    }
    private _rowClickHandler: MyGriddlePlugins.RowClickHandler = 
        (event: React.MouseEvent<Element>, selectedSerialNumber: MyGriddlePlugins.RowId) => {
        if (selectedSerialNumber !== this.props.selectedSerialNumber) {
            /* 
            Set state, dispatch an action, do whatever.  The main point is that you
            now have the actual event from the click on the row and the id value from
            your data in a function on your component.  If you can trigger another
            render pass from here and set a fresh value for this.rowSelector.rowIdToSelect 
            then the "selected" CSS class will be applied to whatever row this click
            event just came form so you can style it however you like. 
            */
        }
    }
    private _rowIdGetter: (rowData: IPartInfo) => MyGriddlePlugins.RowId =
        (rowData: IPartInfo) => rowData.serialNumber;
    public render(): JSX.Element {
        this.rowSelector.rowIdToSelect = this.props.selectedSerialNumber;
        return (
            <div>
                <Griddle
                    data={this.props.parts}
                    plugins={[plugins.LocalPlugin, this.rowSelector.plugin]}
                >
                    <RowDefinition>
                        <ColumnDefinition id="name" title="Part Name" />
                        <ColumnDefinition id="location" title="Installed Location" />
                        <ColumnDefinition id="serailNumber" title="Serial Number" />
                    </RowDefinition>
                </Griddle>
            </div>
        );
    }
}

那么,这里到底发生了什么?组件在实例化时创建插件类的实例,传入一个事件处理程序来捕获行上的单击,并传入一个访问器函数来从数据行中检索ID值(不是不可思议的内部ID)。就在组件返回渲染之前,在组件的插件实例上设置一个值,这样,当Griddle渲染时,插件就有数据来确定它什么时候在选定的行上,然后相应地调整CSS。然后,组件的处理程序函数被分配给该行的onClick处理程序,这样组件就可以从点击中获取数据,并做任何它需要做的事情。

这通过了"它为我工作"测试(在React 15.6上),在我的情况下,这是一个直接的主/细节视图,由一个通过Griddle实现的传统表驱动。我不知道它如何与Griddle的一些更高级的功能一起工作。

最新更新