4

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

我正在用 JQuery 进行实验,甚至用 Griddle 元数据,但它可以用更干净的方式完成吗?

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

我可以通过使用 onClick 事件获取数据,但无法在 onClick 事件中切换背景颜色,或者使用元数据播放。

谢谢 !

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

4

2 回答 2

4

您可以使用 react-griddle 道具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 。

于 2016-09-10T15:36:52.023 回答
3

无论出于何种原因,我根本无法让 Waiski 的答案为我工作。我假设过去两年里 Griddle 一定发生了一些变化。看起来目前网络上流行的建议是“将行选择作为插件实现”,但我也找不到任何例子。在对 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 的一些更高级的功能配合得如何。

于 2018-08-20T00:39:10.093 回答