70

What I want to do is simply to append some html on an element. I checked some links and found different confusing, non-working, non-recommended solutions.

Using JavaScript, I'll do something like this:

var d1 = document.getElementsByClassName('one');
d1.insertAdjacentHTML('beforeend', '<div class="two">two</div>');

How do I achieve the same result using typescript/angular2, RC5?

EDIT

The element with class .one is generated by an external js, and I can't modify it.

5 Answers 5

120

1.

<div class="one" [innerHtml]="htmlToAdd"></div>
this.htmlToAdd = '<div class="two">two</div>';

See also In RC.1 some styles can't be added using binding syntax

  1. Alternatively
<div class="one" #one></div>
@ViewChild('one') d1:ElementRef;

ngAfterViewInit() {
  d1.nativeElement.insertAdjacentHTML('beforeend', '<div class="two">two</div>');
}

or to prevent direct DOM access:

constructor(private renderer:Renderer) {}

@ViewChild('one') d1:ElementRef;

ngAfterViewInit() {
  this.renderer.invokeElementMethod(this.d1.nativeElement', 'insertAdjacentHTML' ['beforeend', '<div class="two">two</div>']);
}
    3.
constructor(private elementRef:ElementRef) {}

ngAfterViewInit() {
  var d1 = this.elementRef.nativeElement.querySelector('.one');
  d1.insertAdjacentHTML('beforeend', '<div class="two">two</div>');
}
Sign up to request clarification or add additional context in comments.

9 Comments

var d1 = this.elementRef.nativeElement.querySelector('.one'); returns null :) I think it executes before it renders the html
This might be related to how you create the .one element. I don't have any information about that.
for some reason, ngAfterviewinit have to be like this: setTimeout(() => { var d1 = this.elementRef.nativeElement.querySelector('.one'); d1.insertAdjacentHTML('beforeend', '<div class="two">two</div>'); }, 1000);
@jcdsr you could try ngAfterContentInit. I don't remember which one executes first.
Does the 3rd solution too prevent Direct Dom Access?
|
31

With the new angular class Renderer2

constructor(private renderer:Renderer2) {}

  @ViewChild('one', { static: false }) d1: ElementRef;

  ngAfterViewInit() {
    const d2 = this.renderer.createElement('div');
    const text = this.renderer.createText('two');
    this.renderer.appendChild(d2, text);
    this.renderer.appendChild(this.d1.nativeElement, d2);
  }

Comments

7

You could do something like this:

htmlComponent.ts

htmlVariable: string = "<b>Some html.</b>"; //this is html in TypeScript code that you need to display

htmlComponent.html

<div [innerHtml]="htmlVariable"></div> //this is how you display html code from TypeScript in your html

3 Comments

My content is generated by an JS, which I cannot modify, and therefore cannot use [innerHtml]
<div [innerHtml]="htmlVariable"></div> - this works if htmlVariable is native html tags, but how to render custom tags? like <div [innerHtml]="htmlVariable"></div> where htmlVariable is '<my-custom-selector></my-custom-selector>? any Idea?
@Stefan SvrkotahtmlVariable: string = "<b *ngIf='somevar=true'>Some html.</b>"; if i use ngIf will it work
5

There is a better solution to this answer that is more Angular based.

  1. Save your string in a variable in the .ts file

    MyStrings = ["one","two","three"]

  2. In the html file use *ngFor.

    <div class="one" *ngFor="let string of MyStrings; let i = index"> <div class="two">{{string}}</div> </div>

  3. if you want to dynamically insert the div element, just push more strings into the MyStrings array

    myFunction(nextString){ this.MyString.push(nextString) }

this way every time you click the button containing the myFunction(nextString) you effectively add another class="two" div which acts the same way as inserting it into the DOM with pure javascript.

1 Comment

eg. MyStrings = ["<div class='my-class'>This is starting", "some dynamic text<br><br> ", "...this is ending</div>"; When we loop through it in the html, angular is auto closing the first <div> and then the last </div> is kind of broken. Another example is if we have some table and td tags in the array opening and closing so we can create the table structure dynamically and add the dynamic text. Output: <div class='my-class'>This is starting</div> some dynamic text this is ending</div> Expected output: <div class='my-class'> some dynamic text ...this is ending</div>
2

When working with Angular the recent update to Angular 8 introduced that a static property inside @ViewChild() is required as stated here and here. Then your code would require this small change:

@ViewChild('one') d1:ElementRef;

into

// query results available in ngOnInit
@ViewChild('one', {static: true}) foo: ElementRef;

OR

// query results available in ngAfterViewInit
@ViewChild('one', {static: false}) foo: ElementRef;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.