【问题标题】:Selecting a Row in React Griddle, and changing tr background color在 React Griddle 中选择一行,并更改 tr 背景颜色
【发布时间】:2016-09-10 14:01:50
【问题描述】:

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

我正在尝试使用 JQuery,甚至使用 Griddle 元数据,但可能会以更简洁的方式完成?

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

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

谢谢!

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

【问题讨论】:

  • 我看过这个库,这可能是 React-griddle 的一个很好的替代品!谢谢!

标签: css reactjs griddle


【解决方案1】:

您可以使用 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 类添加到选定的&lt;tr&gt; 元素,因此您可以use custom styles 为选定的行添加颜色或您想要应用的任何样式。

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

【讨论】:

  • 几乎! ,它现在选择了我所有的行,我试图找出原因......因为你的代码看起来很有意义。我不确定这个属性:rowData.id,因为当您尝试在控制台中记录它时它是未定义的,但是顺便感谢一下,非常感谢;)!
  • @DavidB。显然您的数据没有id 字段。您需要为每一行设置一些唯一标识符才能完成这项工作。您可以将我的代码中的 idrow.props.data.idrowData.id)切换到您拥有的任何唯一字段。
  • 其实元数据声明中无法访问rowData._id,但是_id字段存在(我用的是MeteorJS和MongoDB)
  • @DavidB。那很奇怪。您能否编辑您的问题以显示您如何准确获取数据并渲染 Griddle。
  • 我切换到 React Semantic UI 表并实现了我自己的数据表来解决这个“问题”并处理行选择
【解决方案2】:

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

【讨论】:

  • 正是我一直在寻找的。谢谢!
猜你喜欢
  • 2021-01-01
  • 2018-03-04
  • 2014-06-06
  • 2019-08-30
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多