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

Angular实现点击粗体按钮切换输入文本粗体/常规状态

实现步骤

1. 调整模板代码

先修正按钮组的事件绑定逻辑,并给textarea添加模板引用变量,方便后续操作DOM:

<!-- 按钮组:修正change事件的参数引用 -->
<mat-button-toggle-group #toggleGroup2="matButtonToggleGroup" multiple style="display: flex; align-items: left;" (change)="onFormatChange(toggleGroup2.value)">
     <mat-button-toggle type="button" value="bold"><mat-icon>format_bold</mat-icon></mat-button-toggle>
     <mat-button-toggle type="button" value="italic"> <mat-icon>format_italic</mat-icon></mat-button-toggle>
     <mat-button-toggle type="button" value="underline"><mat-icon>format_underlined</mat-icon></mat-button-toggle>
</mat-button-toggle-group>

<!-- Textarea:添加模板引用变量 #description -->
<textarea #description id="description" matInput placeholder="Description..." formControlName="description" matTextareaAutosize matAutosizeMinRows=10 matAutosizeMaxRows=10></textarea>

2. 组件类逻辑实现

在组件的TS文件中,添加格式状态管理、光标位置插入文本的核心逻辑:

import { Component, ElementRef, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';

@Component({
  // 保留你的组件元数据(selector、templateUrl等)
})
export class YourComponent {
  // 假设你的表单定义如下(根据实际项目调整)
  form = new FormGroup({
    description: new FormControl('')
  });

  // 获取textarea的DOM元素引用
  @ViewChild('description') textarea!: ElementRef<HTMLTextAreaElement>;
  // 记录各格式的激活状态
  formatStates: { [key: string]: boolean } = {
    bold: false,
    italic: false,
    underline: false
  };

  // 快捷获取描述表单控件
  get descriptionControl() {
    return this.form.get('description') as FormControl;
  }

  // 格式按钮组切换事件处理
  onFormatChange(selectedValues: string[]) {
    // 更新每个格式的激活状态
    this.formatStates.bold = selectedValues.includes('bold');
    this.formatStates.italic = selectedValues.includes('italic');
    this.formatStates.underline = selectedValues.includes('underline');

    // 遍历格式,在光标位置插入对应标签
    Object.entries(this.formatStates).forEach(([key, isActive]) => {
      const tagMap = { bold: 'b', italic: 'i', underline: 'u' };
      const tag = tagMap[key as keyof typeof tagMap];
      // 激活时插入开始标签,取消时插入结束标签
      const insertText = isActive ? `<${tag}>` : `</${tag}>`;
      
      this.insertTextAtCursor(insertText);
    });
  }

  // 在光标位置插入文本的工具方法
  private insertTextAtCursor(text: string) {
    const textareaEl = this.textarea.nativeElement;
    const startPos = textareaEl.selectionStart;
    const endPos = textareaEl.selectionEnd;
    const currentValue = textareaEl.value;

    // 拼接新的文本内容
    const newValue = currentValue.substring(0, startPos) + text + currentValue.substring(endPos);
    
    // 更新textarea值和表单控件
    textareaEl.value = newValue;
    this.descriptionControl.setValue(newValue);

    // 将光标定位到插入文本的末尾,保证输入流畅
    textareaEl.selectionStart = textareaEl.selectionEnd = startPos + text.length;
  }
}

3. 效果说明

  • 首次点击粗体按钮,光标位置自动插入<b>标签,后续输入的内容会处于该标签范围内
  • 再次点击粗体按钮,光标位置插入</b>标签,后续输入恢复常规格式
  • 斜体、下划线功能逻辑完全一致,且支持多格式同时激活(比如同时加粗+斜体)

补充优化(可选)

如果需要让用户直观看到富文本效果(而非纯HTML标签),可以添加一个预览区域:

<div class="preview-area" [innerHTML]="descriptionControl.value"></div>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:25:33