Search code examples
angularprimengprimeng-tree

Need to show a textbox on double click for the particular primeng tree node


I have a primeng tree node. When I click the node label, it should turn into a text box but for only to that node. I tried with a Boolean flag, it works but shows up all textbox. Is there a simple fix to show up the text box only for that node?

Here is my code

.ts

import { Component, OnInit } from '@angular/core';
import { NodeService } from './nodeservice';
import { TreeNode } from 'primeng/api';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  nodes: TreeNode[];
  showText = false;

  constructor() {}

  ngOnInit() {
    this.nodes = [
      {
        key: '0',
        label: 'Introduction',
        children: [
          { key: '0-0', label: 'What is Angular' },
          { key: '0-1', label: 'Getting Started' },
          { key: '0-2', label: 'Learn and Explore' },
          { key: '0-3', label: 'Take a Look' },
        ],
      },
    ];
  }

  showTextbox() {
    this.showText = true;
  }
}

.html

<p-tree [value]="nodes">
  <ng-template let-node pTemplate="default">
    <div  *ngIf="!showText" (dblclick)="showTextbox()">
      <b>{{ node.label }}</b>
    </div>
    <div *ngIf="showText">
    <input type="text" [value]="node.label" />
  </div>
  </ng-template>
</p-tree>

Here is the stackblitz link.


Solution

  • This can be achieved by using new flags.

    .html

    <div *ngIf="showTextForNodeId != node.key || !showText"
      (dblclick)="showTextbox(node.key)">
        <b>{{ node.label }}</b>
    </div>
    <div *ngIf="showTextForNodeId == node.key && showText">
      <input type="text"
        [value]="node.label"
        (blur)="updateNode($event.target.value, node.key)"
      />
    </div>
    

    .ts

    showTextForNodeId = undefined;
    showText = false;
    
    showTextbox(key) {
      this.showTextForNodeId = key;
      this.showText = true;
    }
    
    updateNode(newName, key) {
      this.findAndUpdateNode(this.nodes, newName, key);
    
      this.showTextForNodeId = undefined;
      this.showText = false;
    }
    
    findAndUpdateNode(nodes, newName, key) {
      for (let i = 0; i < nodes.length; i++) {
        if (nodes[i].key == key) {
          nodes[i].label = newName;
        } else if (nodes[i].children) {
          this.findAndUpdateNode(nodes[i].children, newName, key);
        }
      }
    }
    

    P.S.: Please check for the edge cases, if they exist.