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

时间:2016-09-10 14:01:50

标签: css reactjs griddle

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

我正在使用JQuery进行实验,甚至使用Griddle元数据,但它可能会以更清洁的方式完成?

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

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

谢谢!

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

2 个答案:

答案 0 :(得分:3)

您可以使用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>类,因此您可以use custom styles添加颜色或要应用于所选行的任何样式。

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

答案 1 :(得分:2)

无论出于何种原因,我都无法获得威斯基为我工作的答案。我假设过去两年来Griddle一定有所改变。看起来Web上当前流行的建议是“将行选择作为插件实现”,但是我也找不到任何示例。在仔细查看了GitHub上Position plugin’s 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的一些更高级的功能配合使用。