Passing HTML button value to .html page in Angular 7

Paul Konstanski
Paul Konstanski used Ask the Experts™
on
In Angular 7, I am trying to determine how to pass a button value through from the typescript  to the html page.

This is the most simple way I can illustrate what I would like to do.  

The .ts file contains this:
this.lessonbody = '<button>Continue</button>';

Open in new window


And in the HTML I'm using this:
        <div [innerHTML]="lessonbody" class="mainbody"></div>

Open in new window


Is there a way to pass that button tag from the .ts file to the .html?

What I am trying to accomplish here is send a code to an API that pulls information from a database and then the whole page is painted from that data. But in order to do this, I need to pass the full html code for things like buttons.

My full code for the .ts file is here:
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormBuilder, FormGroup, Validators, } from '@angular/forms';
import { DomSanitizer } from '@angular/platform-browser';

import { Pagecode } from "../../models/pagecode";
import { PagecodeService } from '../../services/pagecode.service';


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

  lessonhead = "";
  lessonbody = "";
  lessonbutton = "";
  pgref = "0.1";
  loading = false;
  constructor(
    private fb: FormBuilder, 
    private pS: PagecodeService, 
    private sanitizer: DomSanitizer, 
    private router: Router) { } 


  ngOnInit() {
    this.loading = true;
    this.pagecodes = undefined;
    this.getPage(this.pgref);

  }

  pagecodes: Pagecode[];
  getPage(pgref: string): void {
    console.log("at getpage with Page Reference ["+pgref+"]");
    pgref = pgref.trim();
    if (!pgref) { return; }
    const newPagecode: Pagecode = { pgref } as Pagecode;
    
    this.pS.getpage(newPagecode)
      .subscribe((pagecodes: any) => {
        console.log("At check code return (1)");
        console.log(pagecodes);

        if (pagecodes.success) {
          console.log("(1) At send code success");
          this.lessonhead = pagecodes.data.head;
          pagecodes.data.safebody = this.sanitizer.bypassSecurityTrustHtml(pagecodes.data.body);
          this.lessonbody = pagecodes.data.safebody;
          this.lessonbody = '<button>Continue</button>';
//          this.lessonbody = pagecodes.data.body;
          this.lessonbutton = pagecodes.data.button;
        }   
        else {
          console.log("(2)Failure return from at API");
          alert("There was a communications error (sI.168). Please try again. If issue persists, please contact support");
          this.router.navigate(['/']);
        }  
        
      });
  }

  public executeSelectedChange = (event) => {
    console.log(event);
  }
}

Open in new window


And the full .html file is:
<section fxLayout fxLayoutAlign="center center">
    <div fxFlex="500px" fxFlex.xs="100%">
        <div [innerHTML]="lessonhead" class="mainpoint"></div>
        <div [innerHTML]="lessonbody" class="mainbody"></div>
        <button mat-raised-button class="jumbo" color="accent">{{lessonbutton}}</button>
    </div>    
</section>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
Create a pipe to sanitize your html.

pipes/safehtml.pipe.ts [create with CLI ng g p pipes/safeHtml]
@Pipe({
  name: 'safeHtml'
})
export class SafehtmlPipe implements PipeTransform {

  constructor(private sanitizer:DomSanitizer){}

  transform(html: string): any {
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }

}

Open in new window


In your view
<div [innerHTML]="lessonbody | safeHTML"></div>

Open in new window

Paul KonstanskiProject Specialist

Author

Commented:
Okay, that was very helpful to get me started. But I now realize I gave the "simple" version to explain what I was doing, but when I now try my more complex version using Angular Material it doesn't work.  

What I'm trying to pass is an Angular Material Button.  So the value I provided for you to show me how to pass is what's on line 1 below. But what I want to pass is line 2 of this code snippet.
this.lessonbody = '<button>Continue</button>';
this.lessonbody = '<button mat-raised-button>Continue</button>';

Open in new window

In my .html file I have this "test" followed by a hard coded line.  That looks like this.
        <div [innerHTML]="lessonbody | safeHtml"></div>
        <button mat-raised-button color="accent">{{lessonbutton}}</button>

Open in new window

When I inspect the code it shows them being rendered as:

<button mat-raised-button="">Continue</button>
<span class="mat-button-wrapper">Continue</span>
<div class="mat-button-ripple mat-ripple" matripple="" ng-reflect-centered="false" ng-reflect-disabled="false" ng-reflect-trigger="[object HTMLButtonElement]"></div>
<div class="mat-button-focus-overlay"></div>

So although I'm sending the code as "mat-raise-button" that is not rendering correctly. I assume that has to do with the order in which things are being read. Is that correct?

Is there a solution that would allow the button to show up as an Angular Material Button or will I have to render this button using class characteristics.  

Thanks.
Paul KonstanskiProject Specialist

Author

Commented:
I just figured out how to do the second part. That is to simply pass it as a "class"  So I changed my second line to this and it works great:

this.lessonbody = '<button class="mat-raised-button">Continue</button>';

Open in new window


Thanks Julian for helping me solve the most difficult part.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
You are welcome.
Paul KonstanskiProject Specialist

Author

Commented:
If you have a minute sometime can you give me a simple paragraph explanation of "Pipes."  I haven't really understood them. Or point me to a Web site that you feel explains them well.
Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
A pipe is something that takes an input on the one end and emits an output on the other end.

You could build a pipe that simply returns what it is given - resulting in the same output you would have got had you not used the Pipe which is not useful but illustrates a point. The pipe acts as the conduit through which data flows - you decide in the code of that Pipe what to do to the data before it pops out the other side

Take the following example
<div>{{date | dateFormat:yymmdd}}</div>
With the above we are saying - take our date value and send it to the dateFormat pipe along with the string 'yymmdd'

In our pipe we will receive these values as
transform(date: string, format:string): any {
// We can now use the format string to decide how to format the date that we received
// Whatever we return is the value that will ACTUALLY be displayed in the <div> tags
  }

Open in new window


So a pipe is basically a process to transform data into something else before it is used. You can chain pipes so you can send the output of one to another etc. At the start the raw data goes in to the first pipe which massages it into the desired output - this becomes the input for the next pipe (if there is one) until it hits the last pipe which returns the value which then appears as output.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial