antd Tree tree control - after incomplete selection of child nodes, you want to obtain the value of the parent node and interact with the back end

Posted by jcarver on Mon, 27 Dec 2021 11:45:01 +0100

Recently, there is a requirement for a permission tree, and the structure of the tree is relatively deep. If you want to implement it, you can obtain the value of the parent node and pass it to the back end after incomplete selection of the child node.

After incomplete sub node selection, you want to obtain the value of the parent node

As shown in the figure: when you select new user and batch import, you want to transfer the IDs of user list and user management to the back end.

By reading API documentation

onCheck is triggered when the check box is selected. The second parameter is an event object, and its return value is printed as follows:

One attribute, halfCheckedKeys, is the value of the associated parent node. In this way, we can easily get the value and splice it with the selected node to pass it to the background.

onCheck = (checkedKeysValue, e) => {
    console.log('onCheck', checkedKeysValue);
    console.log('e.halfCheckedKeys :>> ', e);
    const checkedKeysResult = [...checkedKeysValue, ...e.halfCheckedKeys]
    this.setState({
        allCheckedId: checkedKeysResult
    })
};

Solve the problem that if the parent node key is passed in during reverse writing, the child node will be selected automatically

There is no problem with the above process when creating a new one. Once the permission tree needs to be backfilled when editing or viewing, there will be a problem, because we are a controlled component and use checkedKeys. Select the tree node of the check box. See API Description:

In this way, if the parent node key is passed in, the child node will be selected automatically. Now deal with this problem.

  • First, when rendering the tree structure, all leaf nodes are stored in an array called childArr
  • Then, compare the id array (with parent node and leaf node) returned by the back-end interface with the childArr array, and take out the same elements (which can be considered to be used) lodash's intersection method)
  • Finally, assign the new array to the checkedKeys of the Tree component

Complete permission tree structure code:

import React from 'react';
import { Tree } from 'antd';
let _ = require('lodash');

let childArr = []   // An array of all child nodes

export default class CmpAuthTree extends React.Component {
    constructor(props) {
        super(props);
        this.getData(this.props.treeData)
        this.state = {
            autoExpandParent: true,
            expandedKeys: this.props.checkedList || [],
            allCheckedId: []   // id array passed to the background
        }
    }

    componentDidMount() {
        this.initData()
    }

    componentDidUpdate(prevProps) {
        this.updateData(prevProps)
    }

    initData = () => {
        let uniqueChild = this.dataClean(this.props.checkedList)
        this.setState({
            checkedKeys: uniqueChild || []
        })
    }

    updateData = (prevProps) => {
        let uniqueChild = this.dataClean(this.props.checkedList)
        if (prevProps.checkedList?.length !== this.props.checkedList?.length) {
            this.setState({
                expandedKeys: this.props.checkedList || [],
                checkedKeys: uniqueChild || []
            })
        }
    }

    getData = (data) => {
        data.map(res => {
            res.title = res.name
            res.key = res.menuId
            if (res.children && res.children.length > 0) {
                this.getData(res.children)
            } else {
                childArr.push(res.menuId)
            }
        })
        return childArr
    }

    dataClean = (checkedList) => {
        let allChildArr = this.getData(this.props.treeData)
        let uniqueChild = _.intersection(checkedList, allChildArr)
        return uniqueChild
    }

    onExpand = (expandedKeysValue) => {
        console.log('onExpand', expandedKeysValue);
        this.setState({
            autoExpandParent: false,
            expandedKeys: expandedKeysValue
        })
    };

    onCheck = (checkedKeysValue, e) => {
        console.log('onCheck', checkedKeysValue);
        console.log('e.halfCheckedKeys :>> ', e);
        const checkedKeysResult = [...checkedKeysValue, ...e.halfCheckedKeys]
        let uniqueChild = this.dataClean(checkedKeysResult)
        this.setState({
            allCheckedId: checkedKeysResult,
            checkedKeys: uniqueChild
        })
    };

    getCheckedList() {
        return this.state.allCheckedId
    }

    render() {
        return <Tree
            // defaultExpandAll
            disabled={this.props.readOnly}
            checkable
            selectable={false}
            onExpand={this.onExpand}
            expandedKeys={this.state.expandedKeys}
            autoExpandParent={this.state.autoExpandParent}
            onCheck={this.onCheck}
            checkedKeys={this.state.checkedKeys}
            treeData={this.props.treeData}
               />
    }
}

success!

Topics: Javascript Front-end React tree antd