13

I just started working on an Angular project but am a bit stuck. I have a component that receives an HTML string from a (trusted) external source. I want to extract and update values from this string, and dispay it in my component.

Now displaying the string is easily done with the following code:

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

My input string has some <span> elements with the data-card-text element attached as identifier. Is it possible to extract this value, and update it whenever my component wants?

Example: let displayString:string = "<svg><text data-card-text>Value I want to update</text></svg>"

Are operations like these even possible in Angular 2?

hY8vVpf3tyR57Xib
  • 3,574
  • 8
  • 41
  • 86

6 Answers6

9

You have to create one Shared Service in which all your global variables are defined like below. Your global variable is "displayString"

export interface SharedModel {
    displayString: string;
    dynamicValue: string;
}

@Injectable()
export class Shared {
    SharedComponent: SharedModel = {
           dynamicValue:'',
           displayString: '<svg><text data-card-text>'+this.SharedComponent.dynamicValue+'</text></svg>'
    };
}

Now access this service in your component where you need to set/get displayString as below.

import { Shared, SharedModel } from '../Shared';
export class MyComponent {
     public sharedData: SharedModel;
     constructor(public sharedResource: Shared)
     {
         this.sharedData = sharedResource.SharedComponent;
     }
}

Assign Value:(it may be in other component/service/APi in your case)

ngOnInit()
{
     this.sharedData.dynamicValue="My name is SANDIP PATEL"
}

Access/Get value in HTML:

<div [innerHTML]="sharedData.displayString"></div>
5

You can use DomSanitizer from platform-browser module

import {DomSanitizer} from '@angular/platform-browser';

Inject DomSanitizer in your component by initializing it in your constructor

  constructor(private domSanitizer: DomSanitizer)

use bypassSecurityTrustHtml() of DomSanitizer and pass your raw html content:

this.displayString= this.domSanitizer.bypassSecurityTrustHtml("<svg><text data-card-text>Value I want to update</text></svg>");

I hope this will solve your problem.

Deepak Kumar
  • 1,669
  • 3
  • 16
  • 36
2

In you component you can just define variable displayString as a public and then you can use it in html

public displayString:string = "<svg><text data-card-text>Value I want to update</text></svg>";
Giga Songulashvili
  • 459
  • 1
  • 4
  • 13
2

This operation doesn't require any angular functionality. One way to do it would be to construct a regular expression to match your string and retrieve the value.

However, you could also create an element using the external string and extract its innerText:

let div = document.createElement('div');
// when the string value changes
div.innerHTML = '<svg><text data-card-text>Value I want to update</text></svg>';

and in your component, set the displayString attribute to this value:

this.displayString = div.innerText;
JusMalcolm
  • 1,431
  • 12
  • 10
1

So, if I understand correctly, you want to update the string value in the <text data-card-text/> element?

If so, you need to use regular expressions in order to extract the string inside the element. The output needs to be saved in a variable (i.e. displayString).

The variable can be added to the template in the following way: <div>{{displayString}}</div>

Stefan
  • 321
  • 1
  • 2
  • 9
1

I do something similar to display an html file constructed by an external application.

I use a wrapper component, passing in the html as an input parameter and implementing the ngOnChanges lifecycle hook to let Angular know there's a change to the html.

import { Component, Input, ElementRef, OnChanges } from '@angular/core';

@Component({
  selector: 'result-wrapper',
  template: `<div data-container></div>`
})
export class ResultWrapper implements OnChanges {

  @Input() displayString: string;

  constructor(
    private elementRef: ElementRef,
  ) {}

  ngOnChanges() {
    this.setPageContent();
  }

  setPageContent() {
    const outerDiv = this.elementRef.nativeElement.querySelector('div[data-container]');
    outerDiv.innerHTML = this.displayString;
  }
}

Changes to the raw html are made in the parent component of ResultWrapper and passed in via attributes.
I use standard document methods as these seem most convenient. For example:

const tempDiv = document.createElement('div');
tempDiv.innerHTML = displayString;
const dataCardText = tempDiv.querySelector('text[data-card-text]');
dataCardText.value = this.myValue;
return tempDiv.innerHTML;

A further note, if you want to style the displayString you should probably add style tags directly to it as Angular will have applied styles defined in @Component before your inner html is updated. Note that styles can 'bleed' into other parts of the page, so make sure they reference the data-container attribute in the wrapper template.

I'm assuming that the tags <svg> and <text data-card-text> may differ at runtime, if not you are obviously better off putting them in the template and interpolating the value. This would not need a wrapper component as {{myValue}} changes would be detected automatically.

@Component({
  selector: 'my-selector',
  template: `<svg><text data-card-text>{{myValue}}</text></svg>`
})
Richard Matsen
  • 20,671
  • 3
  • 43
  • 77