JavaScript markierten Text - Style ändern

-Rayz-

Lieutenant
Registriert
Okt. 2010
Beiträge
897
Guten Tag,

ich habe eine Textarea und kann via DropDown die Schriftgröße / Stärke ändern. Die Änderung erfolgt aber dann immer in der kompletten Textarea. Mit welchem Event kann ich denn nur den markierten Text im Style ändern? Google tut sich da gerade bisschen schwer und ich bekomme nur Suchergebnisse über select option Felder...

Code:
   <select class="browser-default custom-select-sm" formControlName="fontWeight">
   <option *ngFor="let weights of fontWeights" [ngValue]="weights">
   {{ weights}}
   </option>
   </select>
   <select class="browser-default custom-select-sm" formControlName="fontSize">
   <option *ngFor="let sizes of fontSizes" [ngValue]="sizes">
   {{ sizes}}
   </option>
   </select>
  
   <textarea type="text" formControlName="textblock"
   spellcheck="false"
   class="form-text pb-1" [rows]="5"
   [style.font-size.px]="text.get('fontSize').value"
   [style.font-weight]="text.get('fontWeight').value"
   [ngClass]="{'is-invalid' : text.get('textblock').errors}">
   </textarea>

Nutze übrigens Angular.
 
Indem du den maskierten Text in eigene html blöcke unterteilt siehe WYSIWYG Editoren
 
Eigentlich wollte ich zuerst den ckeditor nutzen aber ich will meine Elemente frei platzieren können einfach via Drag & Drop. Die Textelemente bestehen dabei aus einem Textarea Feld. Demnach müsste ich das Textarea Feld in einen html block umändern. Aber selbst wenn ich das mache, muss es ja ein Event für den markierten Text geben oder nicht? Um diesen Text drumherum muss ich ja dann die Formatierung setzen.

PS. hab nun
window.getSelection()
gefunden. Mal sehen ob ich damit weiterkomme.
 
Zuletzt bearbeitet:
window.getSelection sollte nicht auf textarea funktionieren.
Events kommen halt bei Events. Das heißt click Events oder Key Events beispielsweise. Ich weiß, dass das Click event dir die cursor position bei einem Input field geben würde, sicherlich geht das auch bei einer textarea. Vielleicht hilft dir das weiter
 
Das Textarea Feld werde ich gegen <p> eintauschen. Wobei ich dann noch nicht weiß, wie ich dann direkt da reinschreiben kann... dann brauch ich doch wieder irgendein input Feld
 
Ein p-Tag an sich editierbar machen, sollte über das Attribut contenteditable realisierbar sein. Ob damit aber auch alles Andere (Value-Bindings etc.) funktioniert, müsste man mal probieren.
 
Ich finde generell ein p element als Textarea element zu missbrauchen, eine schlechte Idee. Du kommst mit den Events an alle wichtigen Infos dran. Bspw in einer eigene Angular Direktive, solltest du aus den Events auslesen, wo der markierte Text anfängt und wo er aufhört. Das sollte aus den Key / click events auslesbar sein. Ggf. machst du halt ein console.out(event) und schaust dir an, was da drin ist
 
Danke für die Antworten. Für Angular gibt es eine Directive mit einer Standardimplementierung für ControlValueAccessor.
Javascript:
@Directive({
  selector: '[appContentEdit]',
  providers:
    [
      { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => ContenteditDirective), multi: true }
    ]
})
export class ContenteditDirective implements ControlValueAccessor {

  constructor(private elementRef: ElementRef,
              private renderer: Renderer2) { }

  private onTouched = () => {};

  private onChange: (value: string) => void = () => {};

  registerOnChange(onChange: (value: string) => void) {
    this.onChange = onChange;
  }

  registerOnTouched(onTouched: () => void) {
    this.onTouched = onTouched;
  }

  @HostListener('input')
  onInput() {
    if (typeof this.onChange === 'function') {
      this.onChange(this.elementRef.nativeElement.innerHTML);
    }
  }

  @HostListener('blur')
  onBlur() {
    if (typeof this.onTouched === 'function') {
      this.onTouched();
    }
  }

  setDisabledState(disabled: boolean) {
    this.renderer.setAttribute(
      this.elementRef.nativeElement,
      'contenteditable',
      String(!disabled),
    );
  }

  writeValue(value: string): void {
    const normalizedValue = value == null ? '' : value;
    this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', normalizedValue);
  }
}

Funktioniert wie erhofft :-)
 
  • Gefällt mir
Reaktionen: Gee858eeG
Hast du den entsprechenden Stackoverflow oder was auch immer Link zu? Verstehe nicht wann die register-Methoden (registerOnTouched und -Changed) aufgerufen werden und wie.
 
Also als Grundlage hatte ich das hier genommen.
Stackblitz Link
Mein gezeigtes Beispiel wird ja durch den ControlValueAccessor fast von selbst erstellt.
 
  • Gefällt mir
Reaktionen: Gee858eeG
Ein Problem hab ich aber noch..
wenn ich als Content nun <p>Neuer Textblock</p> übergebe, dann nur den Textblock markiere und
document.execCommand('formatBlock', false, 'H3');

aufrufe, wird der komplette Block in H3 umgeändert. Die Markierung wird dabei komplett ignoriert.
Die Lösung dazu wäre zwar sowas:

Javascript:
   const sel = document.getSelection(); // Gets selection
    let selectedHtml = '';
    if (sel.rangeCount) {
      const container = document.createElement('div');
      for (let i = 0, len = sel.rangeCount; i < len; ++i) {
        container.appendChild(sel.getRangeAt(i).cloneContents());
      }
      selectedHtml = container.innerHTML;
    }

    const html = `<h3>${selectedHtml}</h3>`;
    document.execCommand('insertHTML', false, html);

Aber das muss doch auch mit dem formatBlock funktionieren...
 
Zurück
Oben