-2

I'm using this code in my.component.ts file:

// ...
export class MyComponent implements OnInit {
  user: any;
  icons = {
    search: faSearch // FontAwesome icon, it's imported
  };
  textContent = `<div class="input-group">
            <input type="text" name="search-string" placeholder="Search...">
            <div class="input-group-append">
              <button type="submit" class="btn btn-sm btn-default">
                <fa-icon icon="${ this.icons.search }"></fa-icon>
              </button>
            </div>
          </div>`;
// ...

And try to use in my.component.html file like this:

<div [innerHTML]="textContent"></div>

The Angular render this code:

<div class="input-group">
  <div class="input-group-append"></div>
</div>

The other codes missing... any idea why?

netdjw
  • 5,419
  • 21
  • 88
  • 162
  • 1
    This appears to be going against the angular framework. So much that I would question why you're even using angular in the first place. Why are you not using angular for what it's best at (generating html for you)? Seems like a bad design. – mwilson Jul 22 '19 at 22:09

2 Answers2

1

Did you check the console log ? It probably has a message like:

WARNING: sanitizing HTML stripped some content.

This message means that some HTML tags were stripped for security reasons. Using [innerHTML] can be a security issue.

And in this case, it is more a matter of design, imho. I would really just reccommend to put the form elements in the template file (i.e. your my.component.html).

Is there a specific reason why you want to put it in the my.component.ts file?


EDIT:

From the comment section it appears that the reason for this construct is to allow developers to inject html (dynamically) inside this component.

There are a number of ways to accomplish this, one of them is content projection.

<my-component>
  put html in the body.
</my-component>

Inside the my.component.html template file you need to add a <ng-content></ng-content> node. The html of the body will be projected there.

So, the my.component.html could look like this:

<div>
  This is my component:<br>
  <ng-content></ng-content>
</div>

Then when you use "my component", you can do this:

<my-component>

  <div class="input-group">
    <input type="text" name="search-string" placeholder="Search...">
    <div class="input-group-append">
      <button type="submit" class="btn btn-sm btn-default">
        <fa-icon icon="fa-search"></fa-icon>
      </button>
    </div>
  </div>

</my-component>

Optionally, you could move the inner content to a different component and do something like this:

<my-component>
  <my-child-component> </my-child-component>
</my-component>
Community
  • 1
  • 1
bvdb
  • 22,839
  • 10
  • 110
  • 123
  • 1
    I just wanted to put you over 9k. Plus, I agree with this comment/answer – mwilson Jul 22 '19 at 22:10
  • Yes, here is a specific reason. Because this would be a multilevel navigation "constructor" where the developer can define a HTML code as dropdown menu item, like this search form. – netdjw Jul 23 '19 at 06:54
  • @netdjw , I hope this additional edit points you in the right direction of a better solution. – bvdb Jul 23 '19 at 10:01
0

You can use @ViewChild to achieve this. The trick here is to make static:true, which in short skips the angular change detection cycle. You can find more on static prop from this post.

Stackblitz Demo

.html

<div #dataContainer></div>

.ts

import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  icons = {
    search: 'faSearch'
  };
  @ViewChild('dataContainer', { static: true }) dataContainer: ElementRef;

  ngOnInit() {
    this.dataContainer.nativeElement.innerHTML = `<div class="input-group">
            <input type="text" name="search-string" placeholder="Search...">
            <div class="input-group-append">
              <button type="submit" class="btn btn-sm btn-default">
                 <fa-icon icon="${ this.icons.search}"></fa-icon>
              </button>
            </div>
          </div>`;
  }

}
Nidhin Joseph
  • 9,981
  • 4
  • 26
  • 48