首页 > 解决方案 > Kendo React Treeview - 添加新节点时编辑以前的元素

问题描述

目前我正在使用 Kendo React Treelist 组件,我有一个我自己无法解决的问题。当我添加一个元素时,我们可以在这里看到它内联。问题是,当我想再次创建一个时,在我添加一个之后,实体都进入编辑模式。有/有过类似的问题或有想法吗? 添加元素

在这里我们可以看到,新的正在渲染,但旧的也在渲染。这不应该是这样。 加倍元素

在这里你可以看到我的代码:

    import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
    TreeList, TreeListToolbar, mapTree, extendDataItem,
    removeItems, modifySubItems,
    TreeListTextEditor, TreeListBooleanEditor
} from '@progress/kendo-react-treelist';
import { AutoComplete, ComboBox, MultiColumnComboBox, DropDownList, MultiSelect, DropDownTree } from '@progress/kendo-react-dropdowns';

import MyCommandCell from './commandCell.jsx';
import employees from './data';

const subItemsField = 'Children';
const expandField = 'expanded';
const editField = 'inEdit';
var valueOfClasses = { id: "2", text: "Company" };
var parentId = null;
var lastClassname = null;

class DropDownForClasses extends React.Component {
    constructor() {
        super();
    }

    state = {
        nodeClasses: ["1", "2"],
        value: { id: "2", text: "Company" }
    }

    handleChange = (event) => {
        valueOfClasses = event.target.value;
        lastClassname = event.target.value.text;
        this.setState({
            value: event.target.value,
            lastClassId: event.target.text
        });

    }
    componentDidMount = () => {
        fetch('./Api/Nodes/GetAllClassesForKendoDropDown').then(response => {
                if (response.ok) {
                    return response
                } else {
                    throw new Error('Error with fetching data from server');
                }
            })
            .then(response => response.json())
            .then(response => JSON.parse(response))
            .then(
                result => {
                    if (result.length == 0) {
                    } else {
                        this.setState({
                            nodeClasses: result
                        });
                    }
                })
            .catch(error => this.setState({ error }));
    }
    render() {
        const { dataItem, field } = this.props;
        const cellData = dataItem[field];
            return (
                <td>
                    <DropDownList textField="text" dataItemKey="id" data={this.state.nodeClasses} value={this.state.value} onChange={this.handleChange} />
                </td>
            );
        }
}


class CustomCellForClasses extends React.Component {
    render() {
        const { dataItem, field } = this.props;
        const cellData = dataItem[field];
        return (
            <td>
                {dataItem.classId == undefined ? <span >{lastClassname}</span> : <span >{dataItem.classId}</span>}
            </td>
        );
    }
}

class KendoTreeview extends React.Component {

    state = {
        data: employees.slice(),
        expanded: [1, 2, 32],
        classId: 3,
        inEdit: []
    }

    addChild = (dataItem) => {
        const newRecord = this.createNewItem();
        parentId = dataItem.id;

        this.setState({
            inEdit: [...this.state.inEdit, newRecord],
            expanded: [...this.state.expanded, dataItem.id],
            data: modifySubItems(
                this.state.data,
                subItemsField,
                item => item.id === dataItem.id,
                subItems => [newRecord, ...subItems]
            )
        });
    }

    enterEdit = (dataItem) => {
        this.setState({
            inEdit: [...this.state.inEdit, extendDataItem(dataItem, subItemsField)]
        });
    }

    generateGuid = () => {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    //when pressing add after inline editing
    save = (dataItem) => {
        var { isNew, inEdit, ...itemToSave } = dataItem;
        dataItem.id = this.generateGuid();
        dataItem.Class = valueOfClasses.id;

        var allCookies = document.cookie.split(';');
        for (var i = 0; i < allCookies.length; i++)
        document.cookie = allCookies[i] + "=;expires=" + new Date(0).toUTCString();
        document.cookie = dataItem.id;

        var baseUrl = window.location.origin;
        var nameOfEntity = dataItem.name;

        fetch(baseUrl + '/Api/Node/CreateNoteFromClient?parentId=' + parentId + "&classId=" + parseInt(valueOfClasses.id) + "&name=" + nameOfEntity + "&id=" + dataItem.id, {
                method: 'post',
                headers: {
                    'Accept': 'application/json, text/plain, */*',
                    'Content-Type': 'application/json'
                }
            })
            .then(response => {
                if (response.ok) {
                    return response
                } else {
                    throw new Error('Error with fetching data from server');
                }
            })
            .then(
                this.setState({
                    data: mapTree(this.state.data, subItemsField, item => item.id === itemToSave.id ? itemToSave : item),
                    inEdit: this.state.inEdit.filter(i => i.id !== itemToSave.id)
                }));
    }

    cancel = (editedItem) => {
        const { inEdit, data } = this.state;
        if (editedItem.isNew) {
            return this.remove(editedItem);
        }

        this.setState({
            data: mapTree(data, subItemsField,
                item => item.id === editedItem.id ? inEdit.find(i => i.id === item.id) : item),
            inEdit: inEdit.filter(i => i.id !== editedItem.id)
        });
    }

    remove = (dataItem) => {
        this.setState({
            data: removeItems(this.state.data, subItemsField, i => i.id === dataItem.id),
            inEdit: this.state.inEdit.filter(i => i.id !== dataItem.id)
        });

        const nodeId = dataItem.id;
        if (window.confirm('Are you sure, you want to delete this item?')) {
            window.location.href = './Node/Delete/' + nodeId;
        }

    }

    CommandCell = MyCommandCell(this.enterEdit, this.remove, this.save, this.cancel, this.addChild, editField);

    onExpandChange = (e) => {
        this.setState({
            expanded: e.value ?
                this.state.expanded.filter(id => id !== e.dataItem.id) :
                [...this.state.expanded, e.dataItem.id]
        });
    }

    onItemChange = (event) => {
        this.setState({
            data: mapTree(
                this.state.data,
                subItemsField,
                item => item.id === event.dataItem.id ?
                    extendDataItem(item, subItemsField, { [event.field]: event.value }) : item
            )
        });
    }

    //When pressing add new and render inline edit setup
    addRecord = () => {
        const newRecord = this.createNewItem();
        this.setState({
            data: [newRecord, ...this.state.data],
            inEdit: [...this.state.inEdit, { ...newRecord }]
        });
    }

    createNewItem = () => {
        const timestamp = new Date().getTime();
        return { id: null, isNew: true};
    }

    componentDidMount = () => {
        fetch('./Api/Nodes/GetAllNodesWithChildrenForKendo')
            .then(response => {
                if (response.ok) {
                    return response
                } else {
                    throw new Error('Error with fetching data from server');
                }
            })
            .then(response => response.json())
            .then(response => JSON.parse(response))
            .then(
                result => {
                    if (result.length == 0) {
                    } else {
                        this.setState({ data: result.slice()})
                    }
                })
    }

    render() {
        const { data, expanded, inEdit, classId } = this.state;
        return (
            <TreeList
                style={{ overflow: 'auto' }}
                data={mapTree(data, subItemsField, item =>
                    extendDataItem(item, subItemsField, {
                        [expandField]: expanded.includes(item.id),
                        [editField]: Boolean(inEdit.find(i => i.id === item.id))
                    }))
                }
                editField={editField}
                expandField={expandField}
                subItemsField={subItemsField}

                onItemChange={this.onItemChange}
                onExpandChange={this.onExpandChange}
                columns={[
                    { field: 'name', title: 'Name', width: 280, editCell: TreeListTextEditor, expandable: true },
                    //{ field: 'Info', title: 'Info', width: 160, editCell: TreeListTextEditor },
                    { field: 'classId', title: 'Class', width: 160, cell: CustomCellForClasses, editCell: DropDownForClasses },
                    { cell: this.CommandCell, width: 360 }
                ]}
                toolbar={
                    <TreeListToolbar>
                        <button
                            title="Add new"
                            className="k-button k-primary"
                            onClick={this.addRecord}
                        >
                            Add new
                        </button>
                    </TreeListToolbar>
                }
            />
        );
    }
}

ReactDOM.render(
    <KendoTreeview />,
    document.getElementById('KendoTreeview')
);

命令单元:

import * as React from 'react';
import jquery from 'jquery';
window.$ = window.jQuery = jquery;


export default function MyCommandCell(enterEdit , remove, save, cancel, addChild, editField) {
    return class extends React.Component {

        EditPerAjax(rowInfo) {
            //$(document).ready(function () {
                var allCookies = document.cookie.split(';');
                for (var i = 0; i < allCookies.length; i++) {
                    document.cookie = allCookies[i] + "=;expires=" + new Date(0).toUTCString();
                }
                if (rowInfo.id == null) {
                    rowInfo.id = document.cookie;
                };
                $.ajax({
                    url: '/Node/Edit/' + rowInfo.id,
                    type: 'GET',
                    success: function (data) {
                        $('#titleOfEntity').text('Edit: ' + rowInfo.name);
                        $('#contentOfBody').html(data);
                    },
                    error: function () {
                        alert("Something went wrong while fetching partial view!");
                    },
                    cache: true
                });
            //});
        }

        render() {
            const { dataItem } = this.props;

            return dataItem[editField]
                ? (

                    <td>
                        <div className="modal" role="dialog" id="myModal">
                            <div className="modal-dialog" role="document">
                                <div className="modal-content">
                                    <div className="modal-header">
                                        <h3 id="titleOfEntity" className="modal-title"></h3>
                                        <button type="button" className="close" data-dismiss="modal" aria-label="Close" >
                                            <span aria-hidden="true">&times;</span>
                                        </button>
                                    </div>
                                    <div id="createNodeFormModalBody" className="modal-body">
                                        <div id="contentOfBody"></div>
                                    </div>

                                </div>
                            </div>
                        </div>
                        <button
                            className="k-button"
                            onClick={() => save(dataItem)}>
                            {dataItem.isNew
                                ? 'Add'
                                : 'Update'}
                        </button>
                        <button
                            className="k-button"
                            onClick={() => cancel(dataItem)}>{dataItem.isNew
                                ? 'Discard'
                                : 'Cancel'}
                        </button>
                    </td>
                ) : (
                    <td>
                        <div className="modal" role="dialog" id="myModal">
                            <div className="modal-dialog" role="document">
                                <div className="modal-content">
                                    <div className="modal-header">
                                        <h3 id="titleOfEntity" className="modal-title"></h3>
                                        <button type="button" className="close" data-dismiss="modal" aria-label="Close" >
                                            <span aria-hidden="true">&times;</span>
                                        </button>
                                    </div>
                                    <div id="createNodeFormModalBody" className="modal-body">
                                        <div id="contentOfBody"></div>
                                    </div>

                                </div>
                            </div>
                        </div>
                        <button
                            className="k-button"
                            onClick={() => addChild(dataItem)}>
                            Add Node
                        </button>

                        <button className="k-button" id="createModal" data-toggle="modal" data-target="#myModal" data-dismiss="modal" onClick={() => this.EditPerAjax(dataItem)}>Edit</button>
                        <button
                            className="k-button"
                            onClick={() => remove(dataItem)}>
                            Remove
                        </button>

                    </td>
                );
        }
    }
}

标签: reactjsreact-nativekendo-treeviewkendo-react-ui

解决方案


推荐阅读