在 React Griddle 中选择一行,并更改 tr 背景颜色
Selecting a Row in React Griddle, and changing tr background color
我只是想知道是否有人已经能够在 React Griddle 中通过单击(仅一次)来更改行的颜色。
我正在尝试使用 JQuery,甚至使用 Griddle 元数据,但它可能会以更简洁的方式完成?
编辑:我在 MantraJS/Meteor 中使用 React 15,Griddle,使用 Mantra 容器在我的 React 组件中获取数据。
我可以使用 onClick 事件获取数据,但无法在 onClick 事件中切换背景颜色,也无法使用 Metadatas。
谢谢!
编辑:我使用另一个视图来显示 table 的内容,所以现在我不需要更改我的 tables 单元格的背景,但是如果我发现解决方案我会完成这个 post
你可以使用 react-griddle 道具 rowMetadata
和 onRowClick
来做到这一点:
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)}
/>
);
}
}
现在,这会向选定的 <tr>
元素添加 selected
class,因此您可以 use custom styles 添加颜色或任何要应用于选定元素的样式行。
请注意,Griddle Github issues 中要求使用更方便的 API 来选择行。
无论出于何种原因,我根本无法让 Waiski 的答案为我工作。我假设在过去的两年里 Griddle 一定发生了一些变化。看起来网络上目前流行的建议是"implement row selection as a plugin",但我也找不到任何例子。经过长时间仔细查看 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" : ""}
/>
);
}
});
}
}
下面是组件如何使用它的粗略概述。 (请注意,我不得不从一个更大、更复杂的组件中有选择地提取这个示例,因此可能会有一些 errors/inconsistencies;对此感到抱歉。它仍然应该给出该方法的一个很好的整体概念。)
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>
);
}
}
那么,这里到底发生了什么?该组件在实例化时创建插件 class 的一个实例,传入一个事件处理程序以捕获对行的点击和一个访问器函数以检索您的 ID 值(不是 inscrutable 内部 ID)从你的一行数据。就在组件 returns 渲染之前,在插件的组件实例上设置了一个值,这样,当 Griddle 渲染时,插件有数据来确定它何时在选定的行上,然后调整 CSS 相应地。然后将您组件的处理函数分配给该行的 onClick 处理程序,这样您的组件就可以从点击中获取数据并执行它需要执行的任何操作。
这通过了 "It works for me" 测试(在 React 15.6 上),在我的例子中,这是一个简单的 master/detail 视图,由通过 Griddle 实现的传统 table 驱动。我不知道它与 Griddle 的一些更高级功能配合使用效果如何。
我只是想知道是否有人已经能够在 React Griddle 中通过单击(仅一次)来更改行的颜色。
我正在尝试使用 JQuery,甚至使用 Griddle 元数据,但它可能会以更简洁的方式完成?
编辑:我在 MantraJS/Meteor 中使用 React 15,Griddle,使用 Mantra 容器在我的 React 组件中获取数据。
我可以使用 onClick 事件获取数据,但无法在 onClick 事件中切换背景颜色,也无法使用 Metadatas。
谢谢!
编辑:我使用另一个视图来显示 table 的内容,所以现在我不需要更改我的 tables 单元格的背景,但是如果我发现解决方案我会完成这个 post
你可以使用 react-griddle 道具 rowMetadata
和 onRowClick
来做到这一点:
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)}
/>
);
}
}
现在,这会向选定的 <tr>
元素添加 selected
class,因此您可以 use custom styles 添加颜色或任何要应用于选定元素的样式行。
请注意,Griddle Github issues 中要求使用更方便的 API 来选择行。
无论出于何种原因,我根本无法让 Waiski 的答案为我工作。我假设在过去的两年里 Griddle 一定发生了一些变化。看起来网络上目前流行的建议是"implement row selection as a plugin",但我也找不到任何例子。经过长时间仔细查看 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" : ""}
/>
);
}
});
}
}
下面是组件如何使用它的粗略概述。 (请注意,我不得不从一个更大、更复杂的组件中有选择地提取这个示例,因此可能会有一些 errors/inconsistencies;对此感到抱歉。它仍然应该给出该方法的一个很好的整体概念。)
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>
);
}
}
那么,这里到底发生了什么?该组件在实例化时创建插件 class 的一个实例,传入一个事件处理程序以捕获对行的点击和一个访问器函数以检索您的 ID 值(不是 inscrutable 内部 ID)从你的一行数据。就在组件 returns 渲染之前,在插件的组件实例上设置了一个值,这样,当 Griddle 渲染时,插件有数据来确定它何时在选定的行上,然后调整 CSS 相应地。然后将您组件的处理函数分配给该行的 onClick 处理程序,这样您的组件就可以从点击中获取数据并执行它需要执行的任何操作。
这通过了 "It works for me" 测试(在 React 15.6 上),在我的例子中,这是一个简单的 master/detail 视图,由通过 Griddle 实现的传统 table 驱动。我不知道它与 Griddle 的一些更高级功能配合使用效果如何。