【问题标题】:How to set component state based on Material UI selected table rows如何根据 Material UI 选择的表格行设置组件状态
【发布时间】:2017-02-21 02:12:51
【问题描述】:

任何帮助学习者的指针表示赞赏。

我正在尝试构建的内容

具有 2 个输入的表单:

  • 文本字段(患者电子邮件)
  • 一个数组(通过编译选择的表行创建)

我正在尝试将组件状态设置为存储文本字段的值和所选表行的数组,以便可以将状态传递给服务器 onSubmit。

代码(表格行由占位符数据填充)

import React, { Component } from 'react';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import {Table, TableBody, TableFooter, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui/Table';

const tableData = [{
    feedName: 'Flossing habit',
    messageCount: '12 messages'
}, {
    feedName: 'Post exo instructions',
    messageCount: '5 messages'
}, {
    feedName: 'Appointment feedback',
    messageCount: '1 message'
}];

class NewPatient extends Component {
    constructor (){
        super();
        this.state = ({
            email: "",
            feeds: []
        });
        this.setEmail = this.setEmail.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.onRowSelection = this.onRowSelection.bind(this);
    }
    setEmail(event) {
        console.log(event.target.value);
        this.setState({email: event.target.value})
    }
    handleSubmit(event){
        event.preventDefault();
        console.log(this.state);
        //Meteor.call('console', this.state);
        this.setState({email: ''});
    }
    onRowSelection(rows){
        console.log(rows);
        this.setState({feeds: rows})
    }
    render() {
        let availableFeeds = tableData.map(feed=> {
            return (
                <TableRow key={feed.feedName}>
                    <TableRowColumn>{feed.feedName}</TableRowColumn>
                    <TableRowColumn>{feed.messageCount}</TableRowColumn>
                </TableRow>
            )});
        return (
            <form onSubmit={this.handleSubmit}>
                <TextField
                    name='email'
                    value={this.state.email}
                  onChange={this.setEmail}
                  hintText='Patient email address'
                />
                <Table multiSelectable={true} onRowSelection={this.onRowSelection}>
                    <TableHeader displaySelectAll={false}>
                        <TableRow>
                            <TableHeaderColumn>Feed Name</TableHeaderColumn>
                            <TableHeaderColumn>Number of messages</TableHeaderColumn>
                        </TableRow>
                    </TableHeader>
                    <TableBody>
                        {availableFeeds}
                    </TableBody>
                </Table>
                <RaisedButton type="Submit" label="Send" primary={true} />
            </form>
        )
    }
}
;

export default NewPatient;

我面临的问题

设置所选行数组的组件状态。当我使用时:

onRowSelection(rows){
        console.log(rows);
        this.setState({feeds: rows})
    }
  • 选定的行不会保持“选定”状态,状态也不会反映选定的行。
  • 如果我从这里删除setState函数,则突然选择行 - 控制台.Log(行)显示选择的更新数组,只要选择更改,就会将表格远离其重置(例如,如果您选择一行然后移动到文本字段)。

我怀疑,但不确定(如果这是问题,不知道如何使用它,在 http://www.material-ui.com/#/components/table 的文档中找不到任何内容),我需要在“onRowSelection”中添加一个函数操作每行中的“选定”布尔值..?

有没有人有这方面的经验或看到我遗漏的明显东西?

提前感谢所有阅读本文的人!非常感谢任何指向相关链接/文档的建议/指针。

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    在 Ryan at themeteorchef.com 的帮助下找到解决方案后回答:

    主要注意事项:

    1. Material-UI 表格有一个 deselectOnClickaway 属性 - 确保将其设置为 false!

    2。每次选择/取消选择任何其他行或表单的另一部分(类似于 Shouvik Roy 的回答)时,我们需要找到一种方法来为每一行设置“已选择”状态

    import React, { Component } from 'react';
    import TextField from 'material-ui/TextField';
    import RaisedButton from 'material-ui/RaisedButton';
    // import { _ } from 'meteor/underscore';
    import {Table, TableBody, TableFooter, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui/Table';
    
    const tableData = [{
        feedName: 'Flossing habit',
        messageCount: '12 messages',
        selected: false,
    }, {
        feedName: 'Post exo instructions',
        messageCount: '5 messages',
        selected: false,
    }, {
        feedName: 'Appointment feedback',
        messageCount: '1 message',
        selected: false,
    }];
    
    class NewPatient extends Component {
        constructor (){
            super();
            this.state = ({
                email: "",
                feeds: tableData
            });
            this.setEmail = this.setEmail.bind(this);
            this.handleSubmit = this.handleSubmit.bind(this);
            this.onRowSelection = this.onRowSelection.bind(this);
        }
        setEmail(event) {
            console.log(event.target.value);
            this.setState({email: event.target.value})
        }
        handleSubmit(event){
            event.preventDefault();
            console.log(this.state);
            Meteor.call('console', this.state.email);
            this.setState({email: ''});
        }
        onRowSelection(rows){
            const selectedFeeds = [];
            this.state.feeds.forEach((feed, i) => {
                feed.selected = rows.indexOf(i) > -1;
                selectedFeeds.push(feed);
            });
        //  console.log(selectedFeeds);
            this.setState({feeds: selectedFeeds}, () => {
                console.log(this.state.feeds);
            });
        }
        render() {
            let availableFeeds = this.state.feeds.map((feed, i)  => {
                return (
                    <TableRow key={feed.feedName} selected={feed.selected}>
                        <TableRowColumn>{feed.feedName}</TableRowColumn>
                        <TableRowColumn>{feed.messageCount}</TableRowColumn>
                    </TableRow>
                )});
            return (
                <form onSubmit={this.handleSubmit}>
                    <TextField
                        name='email'
                        value={this.state.email}
                      onChange={this.setEmail}
                      hintText='Patient email address'
                    />
                    <Table multiSelectable={true} onRowSelection={this.onRowSelection}>
                        <TableHeader displaySelectAll={false}>
                            <TableRow>
                                <TableHeaderColumn>Feed Name</TableHeaderColumn>
                                <TableHeaderColumn>Number of messages</TableHeaderColumn>
                            </TableRow>
                        </TableHeader>
                        <TableBody deselectOnClickaway={false}>
                            {availableFeeds}
                        </TableBody>
                    </Table>
                    <RaisedButton type="Submit" label="Send" primary={true} />
                </form>
            )
        }
    }
    ;
    
    export default NewPatient;
    

    【讨论】:

      【解决方案2】:

      问题似乎是,当您在组件上设置状态时,render 再次被调用并且您的行被取消选择。解决此问题的最简单方法是读取状态并将selected 设置为TableRow。这是在 React 中实现受控组件的示例,您可以阅读更多 here

      这里是更新的代码:

      import React, { Component } from 'react';
      import TextField from 'material-ui/TextField';
      import RaisedButton from 'material-ui/RaisedButton';
      import {Table, TableBody, TableFooter, TableHeader, TableHeaderColumn, TableRow, TableRowColumn} from 'material-ui/Table';
      
      const tableData = [{
      feedName: 'Flossing habit',
      messageCount: '12 messages'
      }, {
      feedName: 'Post exo instructions',
      messageCount: '5 messages'
      }, {
      feedName: 'Appointment feedback',
      messageCount: '1 message'
      }];
      
      class NewPatient extends Component {
      constructor (){
          super();
          this.state = ({
              email: "",
              feeds: []
          });
          this.setEmail = this.setEmail.bind(this);
          this.handleSubmit = this.handleSubmit.bind(this);
          this.onRowSelection = this.onRowSelection.bind(this);
      }
      setEmail(event) {
          console.log(event.target.value);
          this.setState({email: event.target.value})
      }
      handleSubmit(event){
          event.preventDefault();
          console.log(this.state);
          //Meteor.call('console', this.state);
          this.setState({email: ''});
      }
      onRowSelection(rows){
          console.log(rows);
          this.setState({feeds: rows})
      }
      render() {
          let availableFeeds = tableData.map((feed, i)=> {
              return (
                  <TableRow key={feed.feedName} selected={this.state.feeds[i].selected}>
                      <TableRowColumn>{feed.feedName}</TableRowColumn>
                      <TableRowColumn>{feed.messageCount}</TableRowColumn>
                  </TableRow>
              )});
          return (
              <form onSubmit={this.handleSubmit}>
                  <TextField
                      name='email'
                      value={this.state.email}
                    onChange={this.setEmail}
                    hintText='Patient email address'
                  />
                  <Table multiSelectable={true} onRowSelection={this.onRowSelection}>
                      <TableHeader displaySelectAll={false}>
                          <TableRow>
                              <TableHeaderColumn>Feed Name</TableHeaderColumn>
                              <TableHeaderColumn>Number of messages</TableHeaderColumn>
                          </TableRow>
                      </TableHeader>
                      <TableBody>
                          {availableFeeds}
                      </TableBody>
                  </Table>
                  <RaisedButton type="Submit" label="Send" primary={true} />
              </form>
          )
          }
      }
      ;
      
      export default NewPatient;
      

      【讨论】:

      • 对,我得到一个错误:'无法读取未定义的属性'选定'。 map 函数中的“i”参数是从哪里传入的? IE。 - 如何反应或 javascript 知道我是为了对应行号。我想我可以尝试输入状态数组本身作为参数..
      • 嗯,当你在onRowSelection 函数中打印出rows 时,你能发布你得到的东西吗?
      • 它会弹出一个包含所选行号的数组。
      猜你喜欢
      • 1970-01-01
      • 2017-01-25
      • 2019-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-07
      • 2020-11-18
      • 2019-10-08
      相关资源
      最近更新 更多