如何制作创建/编辑弹出式表单组件

时间:2018-10-11 13:12:58

标签: reactjs typescript user-interface

我正在尝试使用react.js作为前端来制作简单的CRUD示例。

我已经在组件中完成了添加/编辑功能, 但我想在点击时动态调用此组件,并在同一页面上将其显示为弹出窗口或模式窗口,而无需重定向到其他路线。

有人有使用react.js进行此操作的经验吗?

这是我的父组件代码,其中显示了显示城市的项目网格:

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';

interface FetchNaseljeDataState {
    nasList: NaseljeData[];
    loading: boolean;
}

export class FetchNaselje extends React.Component<RouteComponentProps<{}>, FetchNaseljeDataState> {
    constructor() {
        super();
        this.state = { nasList: [], loading: true };
        fetch('api/Naselje/Index')
            .then(response => response.json() as Promise<NaseljeData[]>)
            .then(data => {
                this.setState({ nasList: data, loading: false });
            });
        // This binding is necessary to make "this" work in the callback  
        this.handleDelete = this.handleDelete.bind(this);
        this.handleEdit = this.handleEdit.bind(this);
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : this.renderNaseljeTable(this.state.nasList);
        return <div>
            <h1>Naselje Data</h1>
            <p>This component demonstrates fetching Naselje data from the server.</p>
            <p>
                <Link to="/addnaselje">Create New</Link>
            </p>
            {contents}
        </div>;
    }

    // Handle Delete request for an naselje  
    private handleDelete(id: number) {
        if (!confirm("Do you want to delete naselje with Id: " + id))
            return;
        else {
            fetch('api/Naselje/Delete/' + id, {
                method: 'delete'
            }).then(data => {
                this.setState(
                    {
                        nasList: this.state.nasList.filter((rec) => {
                            return (rec.idnaselje != id);
                        })
                    });
            });
        }
    }
    private handleEdit(id: number) {
        this.props.history.push("/naselje/edit/" + id);
    }

    // Returns the HTML table to the render() method.  
    private renderNaseljeTable(naseljeList: NaseljeData[]) {
        return <table className='table'>
            <thead>
                <tr>
                    <th></th>
                    <th>ID Naselje</th>
                    <th>Naziv</th>
                    <th>Postanski Broj</th>
                    <th>Drzava</th>
                </tr>
            </thead>
            <tbody>
                {naseljeList.map(nas =>
                    <tr key={nas.idnaselje}>
                        <td></td>
                        <td>{nas.idnaselje}</td>
                        <td>{nas.naziv}</td>
                        <td>{nas.postanskiBroj}</td>
                        <td>{nas.drzava && nas.drzava.naziv}</td>
                        <td>
                            <a className="action" onClick={(id) => this.handleEdit(nas.idnaselje)}>Edit</a>  |
                            <a className="action" onClick={(id) => this.handleDelete(nas.idnaselje)}>Delete</a>
                        </td>
                    </tr>
                )}
            </tbody>
        </table>;
    }
}
export class NaseljeData {
    idnaselje: number = 0;
    naziv: string = "";
    postanskiBroj: string = "";
    drzava: DrzavaData = { iddrzava: 0, naziv: ""};
    drzavaid: number = 0;
}

export class DrzavaData {
    iddrzava: number = 0;
    naziv: string = "";
}

这是我要在创建新链接时动态显示的子组件:

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import { Link, NavLink } from 'react-router-dom';
import { NaseljeData } from './FetchNaselje';
import { DrzavaData } from './FetchNaselje';

interface AddNaseljeDataState {
    title: string;
    loading: boolean;
    drzavaList: Array<any>;
    nasData: NaseljeData;
    drzavaId: number;
}

export class AddNaselje extends React.Component<RouteComponentProps<{}>, AddNaseljeDataState> {
    constructor(props) {
        super(props);

        this.state = { title: "", loading: true, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
        fetch('api/Naselje/GetDrzavaList')
            .then(response => response.json() as Promise<Array<any>>)
            .then(data => {
                this.setState({ drzavaList: data });
            });

        var nasid = this.props.match.params["nasid"];
        // This will set state for Edit naselje  
        if (nasid > 0) {
            fetch('api/Naselje/Details/' + nasid)
                .then(response => response.json() as Promise<NaseljeData>)
                .then(data => {
                    this.setState({ title: "Edit", loading: false, nasData: data });
                });
        }
        // This will set state for Add naselje  
        else {
            this.state = { title: "Create", loading: false, drzavaList: [], nasData: new NaseljeData, drzavaId: -1 };
        }
        // This binding is necessary to make "this" work in the callback  
        this.handleSave = this.handleSave.bind(this);
        this.handleCancel = this.handleCancel.bind(this);
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : this.renderCreateForm(this.state.drzavaList);
        return <div>
            <h1>{this.state.title}</h1>
            <h3>Naselje</h3>
            <hr />
            {contents}
        </div>;
    }

    // This will handle the submit form event.  
    private handleSave(event) {

        event.preventDefault();
        const data = new FormData(event.target);
        // PUT request for Edit naselje.  
        if (this.state.nasData.idnaselje) {
            fetch('api/Naselje/Edit', {
                method: 'PUT',
                body: data,
            }).then((response) => response.json())
                .then((responseJson) => {
                    this.props.history.push("/fetchnaselje");
                })
        }
        // POST request for Add naselje.  
        else {
            fetch('api/Naselje/Create', {
                method: 'POST',
                body: data,
            }).then((response) => response.json())
                .then((responseJson) => {
                    this.props.history.push("/fetchnaselje");
                })
        }
    }

    // This will handle Cancel button click event.  
    private handleCancel(e) {
        e.preventDefault();
        this.props.history.push("/fetchnaselje");
    }

    // Returns the HTML Form to the render() method.  
    private renderCreateForm(drzavaList: Array<any>) {
        return (
            <form onSubmit={this.handleSave} >
                <div className="form-group row" >
                    <input type="hidden" name="idnaselje" value={this.state.nasData.idnaselje} />
                </div>
                < div className="form-group row" >
                    <label className=" control-label col-md-12" htmlFor="Naziv">Naziv</label>
                    <div className="col-md-4">
                        <input className="form-control" type="text" name="naziv" defaultValue={this.state.nasData.naziv} required />
                    </div>
                </div >
                <div className="form-group row">
                    <label className="control-label col-md-12" htmlFor="PostanskiBroj" >Postanski broj</label>
                    <div className="col-md-4">
                        <input className="form-control" name="PostanskiBroj" defaultValue={this.state.nasData.postanskiBroj} required />
                    </div>
                </div>
                <div className="form-group row">
                    <label className="control-label col-md-12" htmlFor="Drzava">Država</label>
                    <div className="col-md-4">
                        <select className="form-control" data-val="true" name="drzavaid" defaultValue={this.state.nasData.drzava ? this.state.nasData.drzava.naziv : ""} required>
                            <option value="">-- Odaberite Državu --</option>
                            {drzavaList.map(drzava =>
                                <option key={drzava.iddrzava} value={drzava.iddrzava}>{drzava.naziv}</option>
                            )}
                        </select>
                    </div>
                </div >
                <div className="form-group">
                    <button type="submit" className="btn btn-default">Save</button>&nbsp;
                    <button className="btn" onClick={this.handleCancel}>Cancel</button>
                </div >
            </form >
        )
    }
}

我假设我必须为创建/编辑组件制作css,以使其看起来像弹出窗口...

编辑:如果有人可以使用我的类编写代码示例,我将不胜感激,

2 个答案:

答案 0 :(得分:1)

在父组件中设置点击功能状态,例如:

this.setState({display: true})

在基于条件显示子组件的父组件渲染中,例如:

<div>{(this.state.display) ? <div><childComponent /></div> : ''}</div>

要在模式/弹出窗口中显示子组件,请将该组件放入引导程序或react-response-modal模式中。为此,您必须安装并导入 react-sensitive-modal ,然后 在render方法中,

return (
      <div>
        {this.state.toggleModal ? <div className="container">
                <Modal open={this.state.toggleModal} onClose={this.onCloseModal} center>
                    <div className="header">
                        <h4>{Title}</h4>
                    </div>
                    <div className="body">
                        <div>
                            {this.state.toggleModal ? <someComponent /> : ''}
                        </div>
                    </div>
                </Modal>
        </div> 
        : null}
    </div>
    )

答案 1 :(得分:0)

让弹出窗口组件从父级那里收到一个道具,告诉它是否应该显示它,一个简单的布尔值就可以解决问题。然后,当您想要显示弹出窗口时,只需更改父窗口中的状态即可。