React-sortable-tree: How to save the value of an input field for a specific node

Created on 16 Sep 2017  路  7Comments  路  Source: frontend-collective/react-sortable-tree

Hello,
I used an input field for the title so that user can change the title if required. How to save the value of the input to that specific node? I used onChange for the input but couldn't find a possible way to save the value to the node.
And when input is saved I want to disappear the input text box so that the node appears like a normal node in a react sortable tree. How to achieve this?

question

Most helpful comment

class test extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            treeData: [
                {
                    title: 'Parent1',
                    children: [{ title: 'Child1' }, { title: 'Child2' }],
                },
                {
                    title: 'Parent2',
                    children: [{ title: 'Child1' }, { title: 'Child2' }],
                },
            ],
        };
    }

    render() {
        const getNodeKey = ({ treeIndex }) => treeIndex;

        return (
            <div style={{ height: 400 }}>
                <SortableTree
                    treeData={this.state.treeData}
                    onChange={treeData => this.setState({ treeData })}
                    generateNodeProps={({ node, path }) => ({
                        title: !node.needsTitle ? (
                            node.title
                        ) : (
                            <form
                                onSubmit={event => {
                                    event.preventDefault();
                                    const { needsTitle, ...nodeWithoutNeedsTitle } = node;
                                    this.setState(state => ({
                                        treeData: changeNodeAtPath({
                                            treeData: state.treeData,
                                            path,
                                            getNodeKey,
                                            newNode: nodeWithoutNeedsTitle,
                                        }),
                                    }));
                                }}
                            >
                                <input
                                    autoFocus
                                    value={node.title}
                                    onChange={event => {
                                        const title = event.target.value;

                                        this.setState(state => ({
                                            treeData: changeNodeAtPath({
                                                treeData: state.treeData,
                                                path,
                                                getNodeKey,
                                                newNode: { ...node, title },
                                            }),
                                        }));
                                    }}
                                />
                            </form>
                        ),
                        buttons: [
                            <button
                                className="btn"
                                id={path.length === 1 ? 'btn_add_parent' : 'btn_add_children'}
                                onClick={() =>
                                    this.setState(state => ({
                                        treeData: addNodeUnderParent({
                                            treeData: state.treeData,
                                            parentKey: path[path.length - 1],
                                            expandParent: false,
                                            getNodeKey,
                                            newNode: {
                                                title: '',
                                                needsTitle: true,
                                            },
                                        }).treeData,
                                    }))}
                            >
                                <img
                                    src="/images/add.png"
                                    alt="my image"
                                    width="15"
                                    height="15"
                                />
                            </button>,
                        ],
                    })}
                />
            </div>
        );
    }
}

All 7 comments

Thank you fritz-c. But this didn't work for my case. I have an add button to add children.(See attachment) I need to save the user entered value and I have added it as the onChange in the add button.

21691038_1981300445416329_437315097_n

Following is my code snippet.

class test extends React.Component {
constructor(props) {

    super(props);
    this.state = {

        treeData: [{title: 'Parent1', children: [{title: 'Child1'}, {title: 'Child2'}]},
            {title: 'Parent2', children: [{title: 'Child1'}, {title: 'Child2'}]}],

        input_value:"user_input"
    }
}

handleChange(event) {
    this.setState({
        title: event.target.input_value,
        treeData: changeNodeAtPath({
            treeData: state.treeData,
            path,
            getNodeKey,
            newNode: { node, title },
        }),
    })
}

render() {

    const getNodeKey = ({ treeIndex }) => treeIndex;

    return (        

                    <div>
                        <SortableTree
                            treeData={this.state.treeData}
                            onChange={treeData => this.setState({ treeData })}
                            generateNodeProps={({ node, path }) => ({

                                buttons: [
                                    <button className="btn" id=
                                        {path.length == 1 ? (
                                            "btn_add_parent"
                                        ) : (
                                            "btn_add_children"
                                        )}
                                            onClick={() =>
                                                this.setState(state => ({
                                                    treeData: addNodeUnderParent({
                                                        treeData: state.treeData,
                                                        parentKey: path[1 - 1], //parentKey: path[path.length - 1].. path.lenth=1 here
                                                        expandParent: false,
                                                        getNodeKey,
                                                        newNode:
                                                            {
                                                                title: (
                                                                    <input type="text" value={this.state.input_value} input_value={node.title} onChange={this.handleChange} />
                                                                )
                                                            },
                                                    }).treeData,
                                                }))}
                                    >
                                        <img src="/images/add.png" alt="my image" width="15" height="15"/>
                                    </button>,
                                ],
                            })}
                        />
                    </div>

Any idea on how to resolve this?

class test extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            treeData: [
                {
                    title: 'Parent1',
                    children: [{ title: 'Child1' }, { title: 'Child2' }],
                },
                {
                    title: 'Parent2',
                    children: [{ title: 'Child1' }, { title: 'Child2' }],
                },
            ],
        };
    }

    render() {
        const getNodeKey = ({ treeIndex }) => treeIndex;

        return (
            <div style={{ height: 400 }}>
                <SortableTree
                    treeData={this.state.treeData}
                    onChange={treeData => this.setState({ treeData })}
                    generateNodeProps={({ node, path }) => ({
                        title: !node.needsTitle ? (
                            node.title
                        ) : (
                            <form
                                onSubmit={event => {
                                    event.preventDefault();
                                    const { needsTitle, ...nodeWithoutNeedsTitle } = node;
                                    this.setState(state => ({
                                        treeData: changeNodeAtPath({
                                            treeData: state.treeData,
                                            path,
                                            getNodeKey,
                                            newNode: nodeWithoutNeedsTitle,
                                        }),
                                    }));
                                }}
                            >
                                <input
                                    autoFocus
                                    value={node.title}
                                    onChange={event => {
                                        const title = event.target.value;

                                        this.setState(state => ({
                                            treeData: changeNodeAtPath({
                                                treeData: state.treeData,
                                                path,
                                                getNodeKey,
                                                newNode: { ...node, title },
                                            }),
                                        }));
                                    }}
                                />
                            </form>
                        ),
                        buttons: [
                            <button
                                className="btn"
                                id={path.length === 1 ? 'btn_add_parent' : 'btn_add_children'}
                                onClick={() =>
                                    this.setState(state => ({
                                        treeData: addNodeUnderParent({
                                            treeData: state.treeData,
                                            parentKey: path[path.length - 1],
                                            expandParent: false,
                                            getNodeKey,
                                            newNode: {
                                                title: '',
                                                needsTitle: true,
                                            },
                                        }).treeData,
                                    }))}
                            >
                                <img
                                    src="/images/add.png"
                                    alt="my image"
                                    width="15"
                                    height="15"
                                />
                            </button>,
                        ],
                    })}
                />
            </div>
        );
    }
}

Thank you. This is what I was looking for. But there is a problem.
In this, only one character can be entered in the input field. Just after one letter is entered the input disappears. I want to add more characters there. How to modify it?

@ChathurangiShyalika how did you resolve the input disappearing?

@NickEmpetvee you need to add the utils file somewhere in your project and add this to imports:

import { addNodeUnderParent, changeNodeAtPath } from '../<wherever>/utils/tree-data-utils';
Was this page helpful?
0 / 5 - 0 ratings

Related issues

29er picture 29er  路  5Comments

vaheqelyan picture vaheqelyan  路  4Comments

jorgecuesta picture jorgecuesta  路  4Comments

2503shubham picture 2503shubham  路  3Comments

JonatanGarciaClavo picture JonatanGarciaClavo  路  3Comments