Naman Jain
Naman Jain

Reputation: 411

Adding an array of strings and HTMLDivElements using *ngFor to DOM

I have a requirement for layout something like this enter image description here

I want to use 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>

This is what the output is (Ignore CSS).

enter image description here

Now instead of [object HTMLDivElement] I want a checkbox and text there. Is there a way?

Upvotes: 0

Views: 823

Answers (2)

Nibha
Nibha

Reputation: 271

The best approach to this solution would be using outerHTML property of the created element. And then sanitize it in the HTML component using a pipe.

// .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

Upvotes: 0

David
David

Reputation: 34435

Method #1

You could use the outerHTML property of the html element so that your array only contains string, and then sanitize these strings in the template so that the html can be displayed

component.ts

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

component.html

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

Method #2

Only use one array of mixed strings/HtmlElements like in your example, and in the template decide how to display it based on the type

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>

See stackblitz demo

Upvotes: 1

Related Questions