You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular响应式表单中如何渲染含HTML标签的内容

解决Angular响应式表单中HTML内容渲染问题

在Angular响应式表单场景下,当表单控件绑定的内容包含<i>/<b>等HTML标签时,原生<input>会直接显示标签文本,无法渲染为对应样式,且[innerHTML]无法与formControlName直接结合使用。以下是两种可行的解决方法:


方案一:用contenteditable元素替代原生<input>

利用contenteditable属性让块级元素可编辑,同时支持HTML内容渲染,再同步内容到表单控件。

Component.html

<form [formGroup]="formName">
  <div 
    formControlName="title"
    contenteditable="true"
    (input)="syncContent($event)"
    class="input-like"
  ></div>
</form>

Component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'app-html-form',
  templateUrl: './html-form.component.html',
  styleUrls: ['./html-form.component.css']
})
export class HtmlFormComponent implements OnInit {
  formName!: FormGroup;
  content: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(
    'Solve ur doubts in (<i>StackOverflow</i>)'
  );

  constructor(
    private fb: FormBuilder,
    private sanitizer: DomSanitizer
  ) {}

  ngOnInit(): void {
    this.formName = this.fb.group({
      title: ['']
    });
    // 初始化渲染HTML内容并同步到表单
    const editableEl = document.querySelector('[formControlName="title"]') as HTMLElement;
    if (editableEl) {
      editableEl.innerHTML = this.content.toString();
      this.formName.get('title')?.setValue(this.content);
    }
  }

  syncContent(event: Event): void {
    const target = event.target as HTMLElement;
    // 将编辑后的HTML内容同步到表单控件
    this.formName.get('title')?.setValue(
      this.sanitizer.bypassSecurityTrustHtml(target.innerHTML)
    );
  }
}

配套CSS(模拟原生input样式)

.input-like {
  border: 1px solid #ced4da;
  border-radius: 0.25rem;
  padding: 0.375rem 0.75rem;
  min-height: calc(1.5em + 0.75rem + 2px);
  font-size: 1rem;
  line-height: 1.5;
  color: #495057;
  background-color: #fff;
  cursor: text;
}

.input-like:focus {
  outline: 0;
  border-color: #80bdff;
  box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
}

方案二:自定义指令封装contenteditable表单绑定逻辑

通过自定义指令统一处理contenteditable元素与表单控件的同步,让组件代码更简洁。

自定义指令代码

import { Directive, ElementRef, HostListener, OnInit, Optional } from '@angular/core';
import { NgControl } from '@angular/forms';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Directive({
  selector: '[contenteditableForm]'
})
export class ContenteditableFormDirective implements OnInit {
  constructor(
    private el: ElementRef,
    @Optional() private ngControl: NgControl,
    private sanitizer: DomSanitizer
  ) {}

  ngOnInit(): void {
    // 监听表单控件值变化,同步到元素
    this.ngControl?.valueChanges.subscribe((value: SafeHtml) => {
      if (value.toString() !== this.el.nativeElement.innerHTML) {
        this.el.nativeElement.innerHTML = value.toString();
      }
    });
    // 初始化渲染初始值
    if (this.ngControl?.value) {
      this.el.nativeElement.innerHTML = this.ngControl.value.toString();
    }
  }

  @HostListener('input') onInput(): void {
    // 将编辑后的内容同步到表单控件
    const htmlContent = this.sanitizer.bypassSecurityTrustHtml(
      this.el.nativeElement.innerHTML
    );
    this.ngControl?.control?.setValue(htmlContent);
  }
}

组件中使用指令

Component.html

<form [formGroup]="formName">
  <div 
    contenteditable="true"
    contenteditableForm
    formControlName="title"
    class="input-like"
  ></div>
</form>

Component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Component({
  selector: 'app-html-form',
  templateUrl: './html-form.component.html',
  styleUrls: ['./html-form.component.css']
})
export class HtmlFormComponent implements OnInit {
  formName!: FormGroup;
  content: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(
    'Solve ur doubts in (<i>StackOverflow</i>)'
  );

  constructor(
    private fb: FormBuilder,
    private sanitizer: DomSanitizer
  ) {}

  ngOnInit(): void {
    this.formName = this.fb.group({
      title: [this.content]
    });
  }
}

注意事项

  1. 必须使用DomSanitizer处理HTML内容,避免XSS风险;
  2. 若需要限制单行输入,可给.input-like添加CSS:white-space: nowrap; overflow-x: auto;;
  3. contenteditable元素的行为与原生input略有差异,可根据需求添加额外的事件处理(如回车换行控制)。

内容的提问来源于stack exchange,提问作者Shanu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 12:08:13