简体   繁体   中英

How to update data for table column in react?

Hi i have problem with my table in bootstrap. I am getting data from server about timetable. This data i am saving in state. Next i am creating table. (Two ways of creating mobile and pc, just changing position of days and hours). Every column contains component SubjectColumn (there will be more data in one column like class and subject name). So when I click on this subject column i need to open modal with clicked subject data and after choosing of list of subjects in modal, I have to change subject for new one. I get subject data in my modal but i don't know how to change them for new one. Any idea please?


export class Schedule extends Component {
    static contextType = LoggedInuserContext;

    constructor(props) {
        super(props);
        this.state = {
            editMode: false,
            openModal: false,
            schedule: null,
            modalShow: false,
            mySubjects: null,
            selectedSubject:null
        };

        this.resize = () => this.forceUpdate();
    }

    changeModalState() {
        this.setState({modalShow: !this.state.modalShow})
    }


    selectSubject(subject){
        this.setState({selectedSubject:subject},this.changeModalState);
    }


    componentDidMount() {
        window.addEventListener('resize', this.resize)
        this.getTimeTable().then(r =>
            this.setState({isScheduleLoaded: true})
        );
        this.getMySubjects();
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this.resize)
    }

    async getTimeTable() {
        if (this.context == null) return;
        const response = await fetch('UserController/GetTimeTable/' + this.context.user.id + '/' + this.context.company + '/' + this.context.role.id);
        this.setState({schedule: await response.json()});
    }

    async getMySubjects() {
        if (this.context == null) return;
        const response = await fetch('SubjectTreeController/GetUserSubjectsList/' + this.context.user.id + '/' + this.context.company + '/' + this.context.role.id);
        this.setState({mySubjects: await response.json()});
    }

    createContent() {
        if (!this.state.isScheduleLoaded === true) return;

        let header_data = [];
        let body_data = [];

        //For mobile else pc
        if (window.innerWidth < 768) {
            //Header of table
            this.state.schedule.days.forEach(day => {
                header_data.push(day.name.substring(0, 2))
            });

            //Body of table
            for (let i = 0; i < this.state.schedule.days[0].slots.length; i++) {
                let row = {
                    firstColumn: i,
                    other: []
                };
                this.state.schedule.days.forEach((day, key) => {
                    row.other.push(day.slots[i]);
                });

                body_data.push(row);
            }
        } else {
            //Header of table
            this.state.schedule.days[0].slots.forEach(slot => {
                header_data.push(slot.order)
            });

            //Body of table
            this.state.schedule.days.forEach(day => {
                let row = {
                    firstColumn: [],
                    other: []
                };
                row.firstColumn.push(day.name);
                day.slots.map(slot => row.other.push(slot));
                body_data.push(row);
            });
        }

        let head = this.createTableHead(header_data);
        let body = this.createRows(body_data);

        return (
            <>
                <thead>
                {head}
                </thead>
                <tbody>
                {body}
                </tbody>
            </>
        );
    }

    createTableHead(data) {
        return (
            <tr>
                <td></td>
                {data.map((d, k) => {
                    return (<th key={k} className={"text-center"}> {d} </th>)
                })}
            </tr>
        );
    }

    createRows(data) {
        const items = [];
        for (let i = 0; i < data.length; i++) {
            const row = [];

            for (let j = 0; j < data[i].other.length; j++) {
                if (data[i].other[j].subject !== null) {
                    row.push(<td key={j} className={"text-center "}><SubjectColumn editMode={this.state.editMode}
                                                                                   subject={data[i].other[j].subject}
                                                                                    selectSubject={this.selectSubject.bind(this)}>
                    </SubjectColumn>
                    </td>);
                } else {
                    row.push(<td key={j} className={"text-center "}><SubjectColumn editMode={this.state.editMode}
                                                                                   subject={null}
                                                                                   selectSubject={this.selectSubject.bind(this)}
                                                                                   >
                                                                                   </SubjectColumn>
                    </td>);
                }
            }

            items.push(
                <tr key={i}>
                    <td>{data[i].firstColumn}</td>
                    {row}
                </tr>
            );
        }
        return items;

    }

    loading() {
        if (this.state.schedule === null)
            return (
                <div className={"d-flex flex-column justify-content-center text-center"}>
                    <div>
                        <Spinner animation="grow" variant="success"/>
                        <Spinner animation="grow" variant="danger"/>
                        <Spinner animation="grow" variant="warning"/>
                    </div>
                    <span>Načítam rozvrh</span>
                </div>
            );
    }

    showActionButtons() {
        const items = [];

        if (this.state.editMode) {
            items.push(<Button key={"save"} className={"px-4 mx-1"} variant={"success"}
                               onClick={this.startEditing.bind(this)}>Uložiť</Button>)
        }
        items.push(
            <Dropdown key={"settings"} alignRight>
                <Dropdown.Toggle variant="dark" id="dropdown-basic">
                    <FontAwesomeIcon icon={faCog} size={"lg"}/>
                </Dropdown.Toggle>

                <Dropdown.Menu>
                    <Dropdown.Item onClick={this.startEditing.bind(this)}>Edituj rozvrh</Dropdown.Item>
                </Dropdown.Menu>
            </Dropdown>
        );
        return items;
    }

    startEditing() {
        this.setState({editMode: !this.state.editMode});
    }


    openScheduleSetting() {
        console.log("open");
//        this.setState({openModal: true});
    }

    closeScheduleSetting() {
        console.log("close");

        //      this.setState({openModal: false});
    }

    render() {
        return (
            <div className={"w-100"} id="schedule">
                <div className={"d-flex justify-content-center my-2"}>
                    <h3 className={"my-1 text-left flex-grow-1  pl-2"}>Rozvrh hodín</h3>
                    {this.showActionButtons()}
                </div>
                <Table striped bordered hover>
                    {this.createContent()}
                </Table>
                {this.loading()}
                <ScheduleSelectModal subject={this.state.selectedSubject} subjectslist={this.state.mySubjects} show={this.state.modalShow} onHide={this.changeModalState.bind(this)}>
                </ScheduleSelectModal>
            </div>
        );
    }
}

SubjectColumn

export class SubjectColumn extends Component {

    showModalInParrent(){
        console.log(this.props);
        this.props.selectSubject(this.props.subject);
    }

    createCell() {
        let items = null;
        if (this.props.editMode) {
            if(this.props.subject === null){
                return (  <Button className={"w-100 h-100"} onClick={this.showModalInParrent.bind(this)}>  </Button>)
            }

            items = (
                <Fragment>
                    <Button className={"w-100 h-100"} onClick={this.showModalInParrent.bind(this)}> {this.props.subject.acronym } </Button>
                </Fragment>
            );
            return items;
        } else {
            if(this.props.subject === null){
            return;
            }

            return (this.props.subject.acronym  );
        }
    }

    render() {
        return (
            <div className="w-100 h-100">
                {this.createCell()}
            </div>
        );
    }
}

Modal:

import React, {Component, Fragment} from "react";
import Modal from "react-bootstrap/Modal";
import ButtonGroup from "react-bootstrap/ButtonGroup";
import Button from "react-bootstrap/Button";

export class ScheduleSelectModal extends Component {

   componentDidUpdate(prevProps, prevState, snapshot) {
       console.log("modal props:");
       console.log(this.props.subject);
   }

    createList() {
        let items = [];
        if (this.props.subjectslist !== null)
            this.props.subjectslist.map(subject =>
                items.push(<Button key={subject.id} block className={"my-1"}>{subject.name} </Button>)
            );

        return items;
    }

    renderHeader(){
       if(this.props.subject === null){
           return(
               <p>
                   Vyberťe subjekt ktorý chcete nahradiť
               </p>
           )
       }
       else{
          return(   <p>
              {this.props.subject.name }
          </p>);
        }
    }

    render() {
        return (
            <Modal
                {...this.props}
                size="lg"
                aria-labelledby="contained-modal-title-vcenter"
                centered
            >
                <Modal.Header closeButton>
                    <Modal.Title id="contained-modal-title-vcenter">
                        {this.renderHeader()}
                    </Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <ButtonGroup vertical className={"w-100"}>
                        {this.createList()}
                    </ButtonGroup>
                </Modal.Body>
            </Modal>
        );
    }
}

This loos like my shedule object

Object
id: 1
dateUpdated: "2020-03-24T17:36:48.66"
days: Array(5)
0: {slots: Array(8), id: 1, order: 1, name: "Pondelok", acronym: "PO", …}
1:
slots: Array(8)
0: {order: 0, subject: null, studentGroup: null}
1: {order: 1, subject: null, studentGroup: null}
2: {order: 2, subject: {…}, studentGroup: null}
3:
order: 3
subject:
note: ""
id: 5
name: "Biológia"
acronym: "B"
__proto__: Object
studentGroup: null
__proto__: Object
4: {order: 4, subject: {…}, studentGroup: null}
5: {order: 5, subject: null, studentGroup: null}
6: {order: 6, subject: null, studentGroup: null}
7: {order: 7, subject: null, studentGroup: null}
length: 8
__proto__: Array(0)
id: 2
order: 2
name: "Utorok"
acronym: "UT"
isWeekend: 0
__proto__: Object
2: {slots: Array(8), id: 3, order: 3, name: "Streda", acronym: "ST", …}
3: {slots: Array(8), id: 4, order: 4, name: "Štvrtok", acronym: "ŠT", …}
4: {slots: Array(8), id: 5, order: 5, name: "Piatok", acronym: "PIA", …}
length: 5
__proto__: Array(0)
__proto__: Object

If I've undeerstood your q, this might work for you:

  1. In the modal where you show selectedSubject , replace each value (text) you want to edit with input element.
  2. changing value in input should update state.selectedSubject in Schedule component or you might have state in modal to capture edited selectedSubject , but why duplicating data if you don't have to. I would go with updating parent component state.
  3. Schedule component should have method which will make put (or patch) request with edited data.
  4. Pass this method to the modal.
  5. Add "Save" button to the modal. When you finish editing, clicking on "Save" button should fire passed method.
  6. Optional: you can have success message in your modal (success or error)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM