使用 *ngFor 将字符串数组和 HTMLDivElements 添加到 DOM

Posted

技术标签:

【中文标题】使用 *ngFor 将字符串数组和 HTMLDivElements 添加到 DOM【英文标题】:Adding an array of strings and HTMLDivElements using *ngFor to DOM 【发布时间】:2021-06-02 04:31:06 【问题描述】:

我有这样的布局要求

我想使用 CSS display: grid;

someFunction(data) 
        this.data = data;
        let parentDiv1 = document.createElement('div');
        parentDiv1.className = 'div';
        parentDiv1.textContent = 'Random Inner Text';
        let cb1 = document.createElement('input');
        cb1.type = 'checkbox';
        cb1.className = 'check-box';
        parentDiv1.appendChild(cb1);
        this.tableKey = [
            '',
            `Text: $this.data.someRandomText1`,
            `Text: $this.data.someRandomText2`,
            `Text: $this.data.someRandomText3`,
            `Text: $this.data.someRandomText4`,
            `Text: $this.data.someRandomText5`,
            parentDiv1,
            `Text: $this.data.someRandomText6`,
            `Text: $this.data.someRandomText7`,
            `Text: $this.data.someRandomText8`,
            parentDiv1
        ];
    
<div class="container">
    <div class="table">
        <ng-container *ngFor="let item of tableKey" [innerhtml]="item"></ng-container>
    </div>
</div>

这就是输出(忽略 CSS)。

现在,我想要一个复选框和文本,而不是 [object HTMLDivElement]。有什么办法吗?

【问题讨论】:

你能在这里分享数据吗? 数据只是一个字符串数组data=&lt;string[]&gt;[] 你需要更新你的数据集并实现它。例如,您的 tableKey 将是对象数组。 你可以看到这个。我已经改变了你的数据类型并实现了 if else 逻辑stackblitz.com/edit/… 是的,这是一个解决方案,但我正在寻找一种将strings | HTMLElement 数组从.component.ts 传递到.component.html 的方法 【参考方案1】:

方法#1

您可以使用 html 元素的 outerHTML 属性,使您的数组只包含字符串,然后在模板中清理这些字符串,以便显示 html

component.ts

this.tableKey = ["text1", "text2", 
  parentDiv1.outerHTML, //Convert html element to string

component.html

<div *ngFor="let item of tableKey" [innerHTML]="item | safeHtml ">

方法#2

仅使用一个混合字符串/HtmlElements 数组,如您的示例,并在模板中根据类型决定如何显示它

component.ts

this.tableKey = ["text1", "text2", 
  parentDiv1, //array of mixed elements

// ...
public isString(value: any)

  return typeof(value) ==='string';

component.html

<ng-container *ngFor="let item of tableKey" >

  <div *ngIf="isString(item)" [innerHTML]="item"></div> <!-- display string -->
  <div *ngIf="!isString(item)" [innerHTML]="item.outerHTML | safeHtml" ></div> <!-- display html element -->

</ng-container>

见stackblitz demo

【讨论】:

【参考方案2】:

此解决方案的最佳方法是使用创建元素的outerHTML 属性。然后使用管道在 HTML 组件中对其进行清理。

// .component.ts

export class AppComponent implements OnInit 
  name = "Angular " + VERSION.major;
  tableKey: any[];

  ngOnInit() 
    let parentDiv1 = document.createElement("div");
    parentDiv1.className = "div";
    parentDiv1.textContent = "Random Inner Text";
    let cb1 = document.createElement("input");
    cb1.type = "checkbox";
    cb1.className = "check-box";
    parentDiv1.appendChild(cb1);
    this.tableKey = [
      "Random 1",
      "Random 2",
      "Random 3",
      "Random 4",
      "Random 5",
      "Random 6",
      parentDiv1.outerHTML,
      "Random 7",
      "Random 8"
    ];
  


// .pipe.ts

import 
  Pipe,
  PipeTransform
 from "@angular/core";
import 
  DomSanitizer
 from "@angular/platform-browser";

@Pipe(
  name: 'safeHtml'
)
export class SafeHtmlPipe implements PipeTransform 
  constructor(private sanitized: DomSanitizer) 
  transform(value: string) 
    return this.sanitized.bypassSecurityTrustHtml(value);
  
<div class="container">
  <div *ngFor="let item of tableKey" [innerHTML]="item | safeHTML">
  </div>
</div>

DEMO

【讨论】:

所以基本上你只是复制了我的答案? 不完全是。我的意思是有相似之处,但这是一个非常常见的解决方案。 与我 24 小时前发布的 stackblitz 有何不同?这是完全相同的代码 代码与@naman 发布的类似,我对该代码进行了更改。 唯一的改变是添加丢失的管道(我已经这样做了)并添加 parentDiv1.outerHTML ,我已经这样做了。祝你有美好的一天

以上是关于使用 *ngFor 将字符串数组和 HTMLDivElements 添加到 DOM的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ngFor 中实例化和使用后续数组?

如何在使用 observable 更新数组时更新 *ngFor 以及如何在网站加载时初始化 observable?

ngFor - 无法对对象数组进行排序Angular 5

使用 *ngFor 迭代数组,同时过滤某个属性 [重复]

在 Angular 4 中使用 trackBy 对 *ngFor 数组进行排序

如何使用 ngFor 遍历数组的一部分?