Ich habe diese einfache Winkelkomponente:

@Component({
  selector: 'my-component',
  template: '<p>{{someString}}</p>',
})
export class MyComponent  {
  @Input() someString: string;
}

someString kann eine beliebige Zeichenfolge beliebiger Länge sein. Stellen Sie sich als Beispiel vor, dass der Wert von someString wie folgt lautet:

"If you want my body and you think I'm sexy, come on, sugar, tell me so."

In diesem Fall entspricht der von Angular generierte HTML-Code im Wesentlichen:

<p>If you want my body and you think I'm sexy, come on, sugar, tell me so.</p>

Wie würde ich MyComponent so ändern, dass jedes Vorkommen des Wortes sexy in someString erkannt wird und Angular dieses Wort in ein anderes HTML-Element wie <b> umschließt. In diesem Beispiel würde es also Folgendes erzeugen:

<p>If you want my body and you think I'm <b>sexy</b>, come on, sugar, tell me so.</p>

Was wäre, wenn ich jedes Vorkommen des Wortes sexy in eine Winkelkomponente anstelle eines nativen HTML-Elements einschließen wollte? Würde das einen anderen Ansatz erfordern?

2
snowfrogdev 21 Feb. 2020 im 19:43

3 Antworten

Beste Antwort

Diese Lösung vermeidet die Verwendung von innerHTML und basiert ausschließlich auf Angular-Konstrukten.

@Component({
  selector: 'my-component',
  template: `
  <p>
    <ng-container *ngFor="let segment of segments">
      <span *ngIf="!segment.shouldBeBold()">segment.text</span>
      <b *ngIf="segment.shouldBeBold()">segment.text</b>
    </ng-container>
  </p>
  `,
})
export class MyComponent  {
  @Input() someString: string;

  private wordsToBold = new Set(['sexy', 'body', 'sugar']); 

  get segments() {
    const regex = this.makeRegex();
    const segments = this.someString.split(regex);
    return segments.map(segment => {
      return { text: segment, shouldBeBold: wordsToBold.has(segment.toLowerCase()) };
    });
  }

  private makeRegex() {
    const expression = [...this.wordsToBold].join('\\b|\\b');
    return new RegExp(`(\\b${expression}\\b)+`, 'gi');
  }
}
0
snowfrogdev 24 Feb. 2020 im 18:21

Sie können Folgendes verwenden: Nach dem Rendern des Hauptsatzes können Sie das spezielle Wort durch ein span-Element ersetzen und eine CSS-Klasse anwenden, z. B. .special auf dieses span-Tag.

{Component, Input, ElementRef, AfterViewInit} aus '@ angle / core' importieren;

@Component({
  selector: 'my-component',
  template: '<p>{{sentence}}</p>'
})
export class MyComponent implements AfterViewInit {
  @Input() sentence: string;
  @Input() specialWord: string;

  constructor(private el: ElementRef) {
  }

  ngAfterViewInit() {
    this.el.nativeElement.innerHTML = this.el.nativeElement.
      innerHTML.replace(new RegExp(`${this.specialWord}`, 'g'), 
          `<span class="special">${this.specialWord}</span>`);
  }
}

Um Ihren Code generisch zu halten, können Sie zusätzliches @Input() für ein spezielles Wort verwenden.

In styles.scss Ihrer Anwendung können Sie die CSS-Klasse .special definieren.

.special {
  font-weight: bold;
}

Wenn Sie sich fragen, warum Sie keine ähnliche Logik verwenden können, um den Inhalt von sentence durch Folgendes zu ersetzen:

    this.sentence = this.sentence.replace(new RegExp(`${this.specialWord}`, 'g'),
         `<span class="special">${this.specialWord}</span>`);

Beachten Sie dann, dass Angular die HTML-Tags maskiert und sie so angezeigt werden, wie sie in der Ausgabe sind. Sie sehen also so etwas im Browser anstelle von gestalteten Bereichen.

Hello, it's a <span class="special">beautiful</span> day and I am in a very <span class="special">beautiful</span> city

Aus diesem Grund musste ich das innerHTML manipulieren, damit das Ersetzen erfolgt, nachdem Angular den Satz in DOM gerendert hat.

1
Wand Maker 21 Feb. 2020 im 17:27

Sie können dies versuchen: D.

@Component({
  selector: 'app-test',
  template: `
    <p [innerHTML]="stringFormatted()"></p>
  `,
  styles: []
})
export class TestComponent {

  someString = "If you want my body and you think I'm sexy, come on, sugar, tell me so.";

  stringFormatted() {
    return this.someString.replace(/sexy/g, '<b>sexy</b>');
  }
}
2
Dacuma 21 Feb. 2020 im 17:03