如何在Angular 4中使用Renderer2动态添加子元素

4
我是一名新手,正在学习 Angular 4。我需要在 HTML 列表中添加子元素作为另一个子元素的子元素。
@Component({

  selector: 'my-app',

  template:` 
    <div>
      <ul #root (click)="getChild($event)">root</ul> 
    </div>
`
})

export class App implements OnInit {

  name:string;

  @ViewChild('root') root;
  constructor( private renderer : Renderer2) {

  }

  ngOnInit() {

  }

  getChild(evt) {

    let li = this.renderer.createElement('li');
    let span = this.renderer.createElement('span');
    let text = this.renderer.createText('Child');
    this.renderer.appendChild(span, text);
    this.renderer.appendChild(li, span);
    this.renderer.appendChild(this.root.nativeElement, li)
  }
}

如何动态绑定<li>元素的点击事件,当点击后,应为相应父级<li>下的<ul>添加新的子元素。树应该动态增长n个数字。

期望结果:

<div>
     root
   <ul>
     <li>
         <span> child </span>
         <ul>
            <li>
                <span> child </span>
                <ul>
                    <li>
                       <span> child </span>
                    </li>
                </ul>
            </li>
         </ul>
     </li>             
  </ul>
</div>

每当我点击<li>时,应该用事件在上面的格式中呈现相应的子元素。
欢迎提出解决方案。谢谢。

你的目标是什么?这似乎不是Angular的方式。如果你描述一下你的需求,我们可以帮助你用“Angular的方式”来解决。 - Bunyamin Coskuner
这是一个深度为n的树形结构,每当用户在列表中点击时,它应该呈现出所点击项的子项。需要用Angular实现。 - Navin
它类似于二叉树还是每个节点只有单个子节点,即一个链表? - Bunyamin Coskuner
数据将来自API,这部分我可以处理,但它应该针对所点击的术语,并将那些子项附加在该术语下。 - Navin
1个回答

4
我已经按照以下链接制作了演示文稿:

查看演示

我所做的是创建一个名为NodeComponent的组件,它将创建您的树节点。请注意,本文中保留了HTML标签,且不包含解释。

Node.component.ts

@Component({
  selector: 'my-node',
  template: `
    <span>{{text}}</span>
    <button (click)="addChild()">Add Child!</button>
    <ul>
      <li *ngFor="let child of children">
        <my-node [text]="child"></my-node>
      </li>
    </ul>
  `
})
export class NodeComponent implements OnInit {

  @Input() text;
  children: string[];

  ngOnInit() {}

  addChild() {
    if (!this.children) {
      this.children = [];
    }
    const childText = `${this.text} - ${this.children.length + 1} - child`;
    this.children.push(childText);
  }
}

它接受一个输入参数text,并包含一个按钮以添加更多子节点。当用户点击该按钮时,它会将另一个文本推送到children数组中,这将使Angular向DOM添加另一个my-node组件。
在另一个组件中,您可以按以下方式使用它: <my-node text="root"></my-node> 编辑 查看此嵌套JSON对象的第二个演示 为了从嵌套的JSON对象创建树形结构,请将NodeComponent重构为以下内容。
import { Component, OnInit, Input } from '@angular/core';

export interface NodeItem {
  text: string;
  children?: NodeItem[];
}

@Component({
  selector: 'my-node',
  template: `
    <span>{{options.text}}</span>
    <button (click)="addChild()">Add Child!</button>
    <ul>
      <li *ngFor="let child of options.children">
        <my-node [options]="child"></my-node>
      </li>
    </ul>
  `
})
export class NodeComponent implements OnInit {

  @Input() options: NodeItem;

  ngOnInit() {}

  addChild() {
    if (!this.options.children) {
      this.options.children = [];
    }
    const childText = `${this.options.text} - ${this.options.children.length + 1} - child`;
    this.options.children.push({text: childText});
  }
}

而且,要在另一个组件中使用它,你只需要按照以下步骤进行操作。

<my-node [options]="options"></my-node>

在组件 ts 中
options: NodeItem;

ngOnInit() {
  this.options = {
    text: 'root',
    children: [{
      text: 'root child 1',
    }, {
      text: 'root child 2',
      children: [{
        text: 'root child 2 child 1'
      }]
    }]
  }
}

@Navin 我更新了我的答案。你可以从 JSON 创建树形结构。如果这对你有用,你能否将我的答案标记为已接受? - Bunyamin Coskuner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接