首页 > 解决方案 > function for delete nodes of tree

问题描述

good I am making a tree using primeng, I am doing the functions to be able to delete a node from the tree, I already have this function made that works well when I want to delete a node that has no children, and also when it only has a single child, but I giving problems when deleting a node that has more than one child. I think the problem is in the for of the function but I don't quite realize that it may be

this.nodos = {
            Estado: true, //Booleano
            Respuesta: 'ok', //string
            Dato: [
                {
                    id_nodo: 1, //int
                    padre: undefined, //undefined o int
                    funcion: 'funcion 1', //String (nombre de la función)
                    menu: 'menu', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true },
                    id_funcion: 1, //int
                    orden: 1,//int
                    principal: true //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 2, //int
                    padre: 1, //undefined o int
                    funcion: 'funcion 2', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 2', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 2, //int
                    orden: 2, //int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 3, //int
                    padre: 1, //undefined o int
                    funcion: 'funcion 3', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 3', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 3, //int
                    orden: 3,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 4, //int
                    padre: 1, //undefined o int
                    funcion: 'funcion 4', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 4', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 4, //int
                    orden: 4,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 5, //int
                    padre: 3, //undefined o int
                    funcion: 'funcion 5', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 5', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 5, //int
                    orden: 5,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 6, //int
                    padre: 2, //undefined o int
                    funcion: 'funcion 6', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 6', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 6, //int
                    orden: 6,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 7, //int
                    padre: 3, //undefined o int
                    funcion: 'funcion 7', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 7', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 7, //int
                    orden: 7,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 8, //int
                    padre: undefined, //undefined o int
                    funcion: 'funcion 8', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 8', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 8, //int
                    orden: 8,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 9, //int
                    padre: 8, //undefined o int
                    funcion: 'funcion 9', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 9', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 9, //int
                    orden: 9,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 10, //int
                    padre: undefined, //undefined o int
                    funcion: 'funcion 10', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 10', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 10, //int
                    orden: 10,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
                {
                    id_nodo: 11, //int
                    padre: 10, //undefined o int
                    funcion: 'funcion 11', //String (nombre de la función) lo que hay que mostrar en los recuadros
                    menu: 'menu 11', //String (titulo de la funcion)
                    permitidos: { pasar_a_manual: true, cancelar: false, estado_servicio: true }, //array de booleanos
                    id_funcion: 11, //int
                    orden: 11,//int
                    principal: false //booleano que identifica si el nodo es principal o no
                },
            ]
        }
        
        
        //Cartel Sweet Alert Error

    mostrarCartelError(titulo, contenido) {
        Swal({
            title: '<b style="color:#000;">' + titulo + '</b>',
            html: '<b style="color:#000;">' + contenido + '</b>',
            type: 'error',
            confirmButtonText: 'Aceptar',
            background: 'rgb(0, 120, 106)',
            confirmButtonColor: '#78cbf2',
            timer: 10000
        })
    }

    //Cartel Sweet Alert Correcto

    mostrarCartelBien(titulo, contenido) {
        Swal({
            title: '<b style="color:#000;">' + titulo + '</b>',
            html: '<b style="color:#000;">' + contenido + '</b>',
            type: 'success',
            confirmButtonText: 'Aceptar',
            background: 'rgb(0, 120, 106)',
            confirmButtonColor: '#78cbf2',
            timer: 10000
        })
    }
    
    
    //Variables para la funcion del nodo seleccionado
    label: any
    dataname: any;
    padre: any

    //Funcion si se selecciona un nodo
    onNodeSelect(event) {
        

        var label = event.node.data.id_nodo

        var dataname = event.node.data.name

        var padre = event.node.data.padre

        //muestro los datos del arbol en la tabla
        this.label = label
        this.dataname = dataname
        this.padre = padre

    }
    
    // funcion para borrar un nodo
    borrarNodo(lista,idnodo) {

        //this.mostrarCartelBien("Correcto", "nodo borrado con éxito")

        //indice del nodo a borrar 
        let indice_nodo_borrar = lista.map((_, i) => i).filter(e => lista[e].id_nodo === idnodo);


        //indices de los nodos hijos a borrar 
        let indice_nodo_borrar_hijos = lista.map((_, i) => i).filter(e => lista[e].padre === idnodo);
       
       

        //indice parseado a int del indice del nodo a borrar
        let indice_nodo_borrar_parseado = parseInt(indice_nodo_borrar)

        

        //Si tiene hijos le aviso al usuario que se van a borrar los hijos del nodo seleccionado
        if(indice_nodo_borrar_hijos.length > 0){
            

            Swal({
                title: '<b style="color:#000;">Atención</b>',
                html: '<h5 style="color:#000;">Si borra este nodo también borrara su hijos ¿Desea Continuar?</h5>',
                type: 'warning',
                showCancelButton: true,
                confirmButtonText: 'Si, borrar',
                background: 'rgb(0, 120, 106)',
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                cancelButtonText: 'Cancelar',
            }).then((result) => {
                if(result.value){
                    for (let i = 0; i < indice_nodo_borrar_hijos.length; i++) {
                        
                        //Borro el nodo 
                        this.nodos.Dato.splice(indice_nodo_borrar_parseado,1)
        
                        //Borro los hijos del nodo 
                        this.nodos.Dato.splice(indice_nodo_borrar_hijos[i],1)
                        
                        //Actualizo el árbol
                        this.armarArbol(this.nodos.Dato)
                    }
        
                }
            })
            
         //Si no tiene hijos solo borro el nodo seleccionado
        }
        else{
            Swal({
                title: '<b style="color:#000;">Atención</b>',
                html: '<h5 style="color:#000;">¿Seguro que quiere borrar este nodo?</h5>',
                type: 'warning',
                showCancelButton: true,
                confirmButtonText: 'Si, borrar',
                background: 'rgb(0, 120, 106)',
                confirmButtonColor: '#3085d6',
                cancelButtonColor: '#d33',
                cancelButtonText: 'Cancelar',
            }).then((result) => {
                if(result.value){
                    console.log("no tiene hijos")
                    this.nodos.Dato.splice(indice_nodo_borrar_parseado,1)
                    this.armarArbol(this.nodos.Dato)
                }
            })
            
        }
       
    }
        
//Boton editar tag
.btn-editar{
  background-color:#00786a;
}

//boton nuevo tag
.btn-nuevotag{
  color: #00786a;
  font: 120% Roboto;
  font-weight: 500;
  border: transparent;
  background-color: transparent;
}


.titulo-tipo-tag{
  font: 140% Roboto;
  font-weight: 500;
}


.titulo-mensajes{
  color: #414141;
  font: 22px Roboto;
  font-weight: 500;
  width: 163px;
}

//item barra
/*.item-barra{
  font: 120% Roboto;
}*/

//Estilos arbol
.company.ui-organizationchart .ui-organizationchart-node-content.ui-person {
  padding: 0;
  border: 0 none;
}

.node-header,.node-content {
  padding: .5em .7em;
}

.node-header {
  background-color: #495ebb;
  color: #ffffff;
}

.node-content {
  text-align: center;
  border: 1px solid #404e91;
}

.node-content img {
  border-radius: 50%;
}

.department-cfo {
  background-color: #00786a;
  color: #ffffff;
  border-radius: 20px;
  text-transform: uppercase;
  font-weight: bolder;
}


.department-coo {
  background-color: #a534b6 !important;
  color: #ffffff;
}

.department-cto {
  background-color: #e9286f !important;
  color: #ffffff;
}

.ui-person .ui-node-toggler {
  color: #495ebb !important;
}

.department-cto .ui-node-toggler {
  color: #8a0a39 !important;
}


.node-parent{
  background-color: #e9286f !important;
  color: #ffffff;
  border: 1px solid #000;
}


.boton{
  cursor: pointer;
}
<mat-tab label="Árbol">

            <div class="col-md-12 d-flex">
                <!-- Grafico de Arbol-->

                <div class="col-md-8 mt-4">
                    <mat-tab-group >
                           <mat-tab *ngFor="let lista of lista_arboles; let indice = index" label="{{indice}}">
                               <div class="mt-3 pt-3">
                                    <p-organizationChart [value]="lista" selectionMode="single" [(selection)]="selectedNode"
                                        (onNodeSelect)="onNodeSelect($event)" (onNodeUnselect)="onNodeUnSelect($event)"
                                        styleClass="company">
                                        <ng-template let-node pTemplate="person">
                                            <div class="node-header ui-corner-top">{{node.label}}</div>
                                            <div class="node-content">
                                                <div>{{ node.data.name }}</div>
                                            </div>
                                        </ng-template>
                                        <ng-template let-node pTemplate="department">
                                            {{ node.label }}
                                        </ng-template>
                                    </p-organizationChart>
                                </div>
                            </mat-tab>
        
                    </mat-tab-group>
                </div>

               

                <!-- Fin Graficos de arbol dinamicos -->

                <!-- Tabla dinamica de nodos -->
                <div class="col-md-4 mt-4">
                    <table class="table table-striped">
                        <thead class="text-white" style="background-color: #00786a;">
                            <tr align="center">
                                <th class="font-weight-bolder" colspan="4">Nodo Seleccionado</th>
                            </tr>
                        </thead>
                        <thead>
                            <tr>
                                <th>Id Nodo</th>
                                <th>Funcion</th>
                                <th>Nodo Padre</th>
                                <th>Acciones</th>
                            </tr>
                        </thead>

                        <tbody>
                            <tr>
                                <td ngDefaultControl name="label" [(ngModel)]="label" [innerHTML]="label"></td>
                                <td ngDefaultControl name="dataname" [(ngModel)]="dataname" [innerHTML]="dataname"></td>
                                <td ngDefaultControl name="padre" [(ngModel)]="padre" [innerHTML]="padre"></td>
                                <td>
                                    <div class="row">
                                        <button class="btn btn-sm" type="button" data-toggle="tooltip"
                                            data-placement="top" title="Agregar Nodo"
                                            (click)="!label ? abrirModalAgregarNodo(modal_nuevo_nodo) : abrirModalAgregarNodoHijo(modal_nuevo_nodo_hijo) ">
                                            <img src="../assets/images/btn_nuevo_usuario.png" />
                                        </button>
                                        <button class="btn btn-sm" type="button" data-toggle="tooltip" data-placement="top" title="Editar nodo" [disabled]="!label" (click)="abrirModalEditarNodo(modal_editar_nodo)">
                                            <img src="../assets/images/btn_editar.png" alt="Editar nodo" />
                                        </button>
                                        <button class="btn btn-sm" type="button" data-toggle="tooltip" data-placement="top"title="Borrar nodo" [disabled]="!label" (click)="borrarNodo(nodos.Dato,label)">
                                            <img src="../assets/images/ic_trash.png" height="24px" alt="Borrar nodo" />
                                        </button>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <table style="margin-top: 50px;" class="table table-striped">

                        <thead class="text-white" style="background-color: #00786a;">
                            <tr style="font-weight: bolder;">
                                <th>Id Nodo</th>
                                <th>Funcion</th>
                                <th>Nodo Padre</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr *ngFor="let tree of this.nodos.Dato; let index = index;">
                                <th title="Id nodo" scope="row">{{ tree.id_nodo }}</th>
                                <td title="Nombre la función del nodo">{{ tree.funcion }}</td>
                                <td title="Nodo padre">{{ tree.padre }}</td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                <!-- Fin tabla dinamica de nodos -->
            </div>

        </mat-tab>
    </mat-tab-group>

标签: javascripthtmlcssangular

解决方案


I've provided a solution below. In this example, I've deleted id_nodo 1. But this will work for any node id.

  1. toDeleteList will hold the id_nodos to delete
  2. Push the base id onto the list
  3. Filter the data for all direct children of the base id and return their id
  4. Add those to the list
  5. For each direct child, call this function to repeat the process
  6. After the entire tree is scanned for children, filter the data array to remove any in the toDeleteList
  7. return the filtered list, leaving the original array unaltered

const data=[{id_nodo:1,padre:null},{id_nodo:2,padre:1},{id_nodo:3,padre:1},{id_nodo:4,padre:1},{id_nodo:5,padre:3},{id_nodo:6,padre:2},{id_nodo:7,padre:3},{id_nodo:8,padre:null},{id_nodo:9,padre:8},{id_nodo:10,padre:null},{id_nodo:11,padre:10}];

let toDeleteList = [];
function deleteNode(id){
  toDeleteList.push(id);
  data.filter(d =>d.padre === id)
    .forEach(child=>{
      toDeleteList.push(child.id_nodo);
      deleteNode(child.id_nodo);
    });
  return data.filter(d=>!toDeleteList.includes(d.id_nodo));
}
const result = deleteNode(1);
console.log(result);


推荐阅读