如何在ngx-markdown中使用FormControl并获取输入值?
解决ngx-markdown动态输入框FormControl值无法获取的问题
核心问题分析
你遇到的问题本质是动态生成的HTML输入框未被Angular表单系统正确绑定:
- 你在
markdownService.renderer.html回调中动态添加FormControl,时机晚于Angular表单初始化,导致控件关联失效; - ngx-markdown渲染的HTML是静态插入的,Angular不会自动编译其中的
formControlName指令,表单无法追踪输入框值变化。
分步解决方案
1. 提前解析并添加FormControl
先从原始Markdown数据中提取所有需要生成的文本框,提前将FormControl添加到表单中,确保渲染前控件已存在:
export class MarkDownComponent implements OnInit, AfterViewInit { @Input() public mdData: any; @ViewChild('markdownEl') markdownEl: ElementRef; markdownForm: FormGroup; constructor( private markdownService: MarkdownService, private formBuilder: FormBuilder, private cdr: ChangeDetectorRef ) {} ngOnInit(): void { // 初始化表单 this.markdownForm = this.formBuilder.group({ name: new FormControl(''), }); // 提前提取所有@TextBox标记,添加对应FormControl const textBoxMatches = this.mdData.match(/@\TextBox\b\((.*?)\)/g) || []; textBoxMatches.forEach(match => { const value = match.replace(/@\TextBox\b\((.*?)\)/, '$1'); const label = value.replace(/ +/g, '').toLowerCase(); if (!this.markdownForm.contains(label)) { this.markdownForm.addControl(label, new FormControl('')); } }); // 替换Markdown中的标记为inject标签 this.mdData = this.mdData.replace( /@\TextBox\b\((.*?)\)/g, "<inject key='$1' value='$1' name='textbox'></inject>" ); // 配置markdown渲染器 this.markdownService.renderer.html = (inject: string) => { if (inject === '</inject>') return ''; const elm = stringToHtml(inject); if (!elm) return ''; const name = elm.getAttribute('name'); const value = elm.getAttribute('value'); if (name === 'textbox') { const label = value.replace(/ +/g, '').toLowerCase(); // 返回带formControlName的输入框HTML return `<input type='text' formControlName='${label}' name='${label}' />`; } return ''; }; this.cdr.detectChanges(); }
2. 手动绑定输入框与FormControl
由于动态生成的HTML无法被Angular自动编译,在视图初始化后,手动建立输入框与FormControl的双向绑定:
ngAfterViewInit(): void { const inputs = this.markdownEl.nativeElement.querySelectorAll('input[formControlName]'); inputs.forEach((input: HTMLInputElement) => { const controlName = input.getAttribute('formControlName'); const control = this.markdownForm.get(controlName); if (!control) return; // 输入框值变化时更新FormControl input.addEventListener('input', () => { control.setValue(input.value, { emitEvent: false }); }); // FormControl值变化时同步输入框 control.valueChanges.subscribe(val => { if (input.value !== val) { input.value = val; } }); // 同步初始值 input.value = control.value; }); } } // 辅助函数:将字符串转为DOM元素 function stringToHtml(str: string): Element | null { const parser = new DOMParser(); const doc = parser.parseFromString(str, 'text/html'); return doc.body.firstElementChild; }
3. 修改HTML模板
给markdown组件添加模板引用变量,方便后续获取DOM元素:
<form [formGroup]="markdownForm"> <markdown #markdownEl [data]="mdData"></markdown> </form>
测试获取值
现在你可以通过以下方式获取输入框的值:
// 获取单个控件值 const textBoxValue = this.markdownForm.get('yourLabel').value; // 获取整个表单的值 const formValues = this.markdownForm.value;
内容的提问来源于stack exchange,提问作者Hiren Nakrani
相关产品推荐
相关产品推荐

