I'm a volunteer at a Coffee Shop. I've built an app that presents the drink recipe to the barista. Here's a quick snapshot:
The data come from a firebase realtime database. Here's a snippet from that database:
What I want to do is to put some HTML into the instructions to format it for easy reading. I do that by binding the content in the template file to [innerHTML] as shown below:
<ion-item>
<ion-grid>
<ion-row *ngIf="!item.temperature">
<ion-col>
<ion-label><strong>Instructions</strong></ion-label>
</ion-col>
</ion-row>
<ion-row>
<ion-col>
<h5 *ngIf="this.compactMode">
<span [innerHTML]="item.instructions"></span>
</h5>
<span *ngIf="!this.compactMode" [innerHTML]="item.instructions">
</span>
</ion-col>
<ion-col *ngIf="item.image"
><ion-img
(click)="onClickImage(item.image)"
src="{{item.image}}"
></ion-img
></ion-col>
</ion-row>
</ion-grid>
</ion-item>
THE PROBLEM
This works really well for <b> <ol> <ul> <li> <br>
and so on. But it does not work for <ion-checkbox>
nor <input type="checkbox">
The input tags get filtered out somewhere before being presented.
SECURITY I'm aware that putting HTML into a database can increase my security surface, so I'm using sanitizer to filter the HTML and then I attempt to add the after the fact. Here's how I do it:
stringFormat(inputString: string) {
const re1 = /\[\]/gi;
let returnString = this.sanitizer.sanitize(1, inputString);
returnString = returnString.replace(re1, '<ion-checkbox id=\'input\'></ion-checkbox>');
return returnString;
}
You'll notice that I first sanitize the string, and then I do a substitution, replacing []
with the checkbox.
(In case you're interested, I'm just making a opening/closing checklist and it would be nice if people could touch the checkbox after they've completed a task... I don't plan to store the checkbox values, I just want the checkbox user experience.)
I have checked that item.instructions in fact includes the substituted string in the item object, but when rendered by ionic/angular, the actual text seems to have filtered out anything but vanilla HTML tags.
Finally the Question So here's the question: Are there some sort of limits to what can be inserted into the DOM using [innerHTML] binding? Am I overthinking this?
Thanks.
After reading https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML, I've concluded that there really is not a safe way to do this using the approach suggested above.
Instead of embedding HTML in the database, I'm going to set up an array of paragraphs in the
item.instructions
fields of the database. Each element in the array can have a key:value pair to indicate if the element represents a plain paragraph, or a checkbox.Then I can iterate through the array of instructions (
*ngFor
), and for each instruction I can check the instruction type (<div *ngIf="item.type===...>
) to determine whether to wrap the text with an<ion-text>
or an<ion-checkbox>
.