首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

动态插入组件时ControlValueAccessor不工作

基础概念

ControlValueAccessor 是 Angular 框架中的一个接口,用于在自定义表单控件和 Angular 表单 API 之间进行通信。它允许开发者创建自定义的表单控件,并使其能够与 Angular 的表单系统无缝集成。

相关优势

  1. 灵活性:通过实现 ControlValueAccessor,可以创建高度自定义的表单控件。
  2. 一致性:自定义控件可以与 Angular 的内置表单控件一样使用,保持表单的一致性。
  3. 可维护性:将复杂的 UI 控件逻辑封装成自定义控件,便于代码的维护和重用。

类型与应用场景

  • 自定义输入框:如日期选择器、颜色选择器等。
  • 复杂组件:如动态表单、可编辑表格等。
  • 第三方组件集成:使第三方 UI 库的组件能够与 Angular 表单系统集成。

常见问题及原因

问题描述:动态插入组件时,ControlValueAccessor 不工作。

可能原因

  1. 变更检测未触发:Angular 的变更检测机制可能未检测到组件的插入。
  2. 实例化顺序问题:组件可能在 Angular 表单系统初始化之后才被插入。
  3. 注册问题:自定义控件可能未正确注册为表单控件。

解决方案

1. 确保变更检测触发

使用 ChangeDetectorRef 手动触发变更检测:

代码语言:txt
复制
import { ChangeDetectorRef } from '@angular/core';

constructor(private cdr: ChangeDetectorRef) {}

ngAfterViewInit() {
  this.cdr.detectChanges();
}

2. 使用 ViewContainerRef 动态插入组件

确保在 Angular 的变更检测周期内插入组件:

代码语言:txt
复制
import { ComponentFactoryResolver, ViewContainerRef } from '@angular/core';
import { MyCustomComponent } from './my-custom.component';

constructor(private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef) {}

ngOnInit() {
  const componentFactory = this.componentFactoryResolver.resolveComponentFactory(MyCustomComponent);
  const componentRef = this.viewContainerRef.createComponent(componentFactory);
}

3. 正确注册自定义控件

确保自定义控件实现了 ControlValueAccessor 接口,并在模块中声明:

代码语言:txt
复制
import { forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export class MyCustomComponent implements ControlValueAccessor {
  // 实现 ControlValueAccessor 接口的方法
}

@NgModule({
  declarations: [MyCustomComponent],
  exports: [MyCustomComponent],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyCustomComponent),
      multi: true
    }
  ]
})
export class MyCustomModule {}

示例代码

假设我们有一个自定义的日期选择器组件 MyDatePicker,它实现了 ControlValueAccessor 接口。

代码语言:txt
复制
import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'my-date-picker',
  template: `<input type="date" [(ngModel)]="value" (ngModelChange)="onChange($event)">`,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyDatePicker),
      multi: true
    }
  ]
})
export class MyDatePicker implements ControlValueAccessor {
  value: string;

  onChange: any = () => {};
  onTouched: any = () => {};

  writeValue(value: string): void {
    this.value = value;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

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

在父组件中动态插入 MyDatePicker

代码语言:txt
复制
import { Component, ComponentFactoryResolver, ViewContainerRef } from '@angular/core';
import { MyDatePicker } from './my-date-picker.component';

@Component({
  selector: 'app-parent',
  template: `<ng-container #container></ng-container>`
})
export class ParentComponent {
  constructor(private componentFactoryResolver: ComponentFactoryResolver, private viewContainerRef: ViewContainerRef) {}

  ngAfterViewInit() {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(MyDatePicker);
    const componentRef = this.viewContainerRef.createComponent(componentFactory);
  }
}

通过以上步骤,可以确保动态插入的组件能够正确地与 Angular 的表单系统集成。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

(转) 别再对 Angular 表单的 ControlValueAccessor 感到迷惑

然后我将展示如何封装第三方组件作为 Angular 组件,以及如何使用输入输出机制实现组件间通信(译者注:Angular 组件间通信输入输出机制可参考官网文档),最后将展示如何使用 ControlValueAccessor...官方文档是这么描述的(译者注:为清晰理解,该描述不翻译): ControlValueAccessor acts as a bridge between the Angular forms API and...:意思就是上面代码中绑定的 formControl 指令,在其自身实例化时,会调用 setUpControl() 函数给同样绑定到 input的 DefaultValueAccessor 指令做好安装工作...组件封装器 由于 Angular 为所有默认原生控件提供了控件值访问器,所以在封装第三方插件或组件时,需要写一个新的控件值访问器。...image.png 如果你把简单封装和 controlValueAccessor 封装进行比较,你会发现父子组件交互方式是不一样的,尽管封装的组件与 slider 组件的交互是一样的。

3.8K20

Angular6自定义表单控件方式集成Editormd

曾经找到过“Editor.md”,看之心喜,一直想在Angular中集成下这款markdownpad编辑器玩,在网上也只找到一篇通过指令集成的,虽然可以实现,但还是希望能做成组件形式的,之后看到一篇自定义组件的文章...ControlValueAccessor 这是自定义表单组件的核心,只有继承这个接口,才有被 Angular的formControl识别的资格。...(isDisabled: boolean):设置DISABLED状态时做的执行的方法。即,当控件状态变成 DISABLED 或从 DISABLED 状态变化成 ENABLE 状态时,会调用该函数。...准备工作 经过上面大致了解ControlValueAccessor,在正式开始前还需要最后的准备工作: 使用npm或者yarn安装jquery npm install jquery 或者 yarn add...这里是用来处理存在默认值时。

5.2K20
  • TDesign 更新周报(2022年6月第2周)

    存在不兼容更新FeaturesTable:筛选对话框输入筛选内容之后按回触发筛选过滤筛选功能支持自定义组件方式,示例:columns:[{ filter:{ component:DatePicker,...props:{} } }]拖拽调整宽度,支持设置最小宽度和最大宽度 column.resize拖拽排序事件,新增参数 data 和 newData,分别表示变更前后的数据Popup:支持动态设置 trigger...组件Bug FixesPopup:修复初始化 visible 为 true 时的定位抖动问题Table:修复树形结构拖拽排序引起展开收起异常问题修复动态数据场景下合并单元格支持Select:修复 inputProps...Dialog:移除 transform 动画方案,dom 结构有所调整,存在不兼容更新InputAdornment:移除 Addon 组件,替换为 InputAdornment,用法保持一致只需更改组件名即可...,存在不兼容更新Featurestable:树形结构,支持默认展开全部,以及自由控制展开全部或收起全部table:树形结构,支持空数据插入新节点、当前数据之前插入新节点、当前数据之后插入新节点、获取树形结构等方法

    89720

    Vue进阶部分文档研读和学习

    -- 这里写当父组件引用子组件但没写内部内容时展示的东东 --> slot的name属性来指定标签插入的位置,也就是文档里面的具名插槽(这个官方文档说的明白) 在子组件的模板里面写的...==name放到正确的位置 没有指明slot属性的就会默认放到匿名插槽的位置上 动态组件 动态组件这个特性,很多人写的Vue项目也不少,但也没用到过这个,有必要多说几句 动态组件适用情况: 单页应用,部分组件的切换不涉及路由...包裹动态组件时,会缓存不活动的组件实例,提高性能,避免重复渲染(keep-alive不会渲染额外DOM结构) 有include和exclude这两个属性,...用于指定缓存和不缓存的组件(传入字符串/数组/正则) 另一种避免重新渲染的方法是为标签增加属性v-once,用于缓存大量的静态内容,避免重复渲染。...ps:不会在函数式组件中正常工作,因为它们没有缓存实例。

    1.3K70

    如何给多个页面,添加统一的导航栏?我罗列对比了 5 个方案

    综上,如果你的网站本身没有服务端渲染,我不建议你仅仅为了增加导航栏而采用该方案。方案二:前端编译时插入前端增加编译环节,源代码不写导航栏,编译后,自动在特定位置插入导航栏的html片段。...(UMD、模块联邦)通过script动态引入导航js,运行时插入html片段(即UMD方式,Webpack的模块联邦也属于这种方案)。...因为导航栏的一致性和可变性,开发时它一定是只存了一份代码的。因为本方案不在编译时统一插入,而是在运行时动态插入,所以就需要多个页面引入同一份js文件,动态插入一样的导航栏。...可以让多页面应用(MPA)体验像单页面应用(SPA)一样(即切换页面时,导航栏不闪烁)。缺点重。如果你的项目本身不是基于微前端的,没有必要为了加导航栏而引入微前端方案。...html片段无最快很好导航html片段在前端项目,需维护好它通过script动态引入导航js,运行时插入html片段无快一般同上基于框架组件(React、Vue等)做导航栏必须统一框架快一般同上基于微前端做导航栏

    8.2K171

    React-组件-TaggedTemplateLiterals

    前言React-组件-TaggedTemplateLiterals是一项强大的React技术,它结合了React组件和模板文字标记。这种方法允许您在编写React组件时更灵活地处理模板文字字符串。...这种方法的优势在于您可以将动态数据嵌入到模板文字中,同时保持React组件的可读性和可维护性。您可以使用Tagged Template Literals来构建更复杂的UI结构,使组件更具通用性。...总之,React-组件-TaggedTemplateLiterals是一种扩展React开发工具箱的方式,可以提高您的组件开发效率,并使您能够更轻松地处理动态内容和UI结构。...);}test`1, 2, 3, ${name}, ${age}`;图片总结结论我们可以拿到模板字符串中所有的内容我们可以拿到模板字符串中所有非插入的内容我们可以拿到模板字符串中所有插入的内容所以我们就可以对模板字符串中所有的内容进行单独的处理图片最后本期结束咱们下次再见...~ 关注我不迷路,如果本篇文章对你有所帮助,或者你有什么疑问,欢迎在评论区留言,我一般看到都会回复的。

    15921

    Angular DOM 抽象概述

    模板元素是一种机制,允许包含加载页面时不渲染,但又可以随后通过 JavaScript 进行实例化的客户端内容。我们可以将模板视作为存储在页面上稍后使用的一小段内容。...Angular 没有什么神奇之处,如果你想要插入新的组件或元素,你需要告诉 Angular 在哪里插入新的元素。...动态创建组件的流程如下: 获取装载动态组件的容器 在组件类的构造函数中,注入 ComponentFactoryResolver 对象 调用 ComponentFactoryResolver 对象的 resolveComponentFactory...() 方法创建 ComponentFactory 对象 调用组件容器对象的 createComponent() 方法创建组件并自动添加动态组件到组件容器中 基于返回的 ComponentRef 组件实例...entryComponents - 用于指定在模块定义时,需要编译的组件列表。

    3.5K30

    【简答题】月薪4k和月薪8k的区别就在这里

    静态查找与动态查找分别是什么? 静态查找表:查找表的操作不包含对表的修改操作。也就是仅对查找表进行查找或读表元操作。...动态查找表:若在查找的同时插入了表中不存在的记录,或从查找表中删除了已存在的记录。 动态表查找有什么特点?...表结构本身是在查找过程中动态生成的,即对于给定值key,若表中存在关键字值等于key的记录,则查找成功返回;否则插入关键字值等于key的记录。 什么是二叉排序树?...v-if 和 v-show 的区别 v-if 在编译过程中会被转化成三元表达式,条件不满足时不渲染此节点。...服务间异步通信 顺序消费 定时任务 请求削峰 RabbitMQ有哪几种常见的工作模式?

    36330

    React 面向组件编程知识

    箭头函数(ES6 模块化编码时才能使用) 组件的组合 功能界面的组件化编码流程 拆分组件: 拆分界面,抽取组件 实现静态组件: 使用组件实现静态页面效果 实现动态组件 a....动态显示初始化数据 b. 交互功能(从绑定事件监听开始) 收集表单数据 问题: 在 react 应用中, 如何收集表单输入数据 包含表单的组件分类 a....非受控组件: 需要时才手动读取表单输入框中的数据 组件生命周期 组件对象从创建到死亡它会经历特定的生命周期阶段 React 组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调 我们在定义组件时..., 可以重写特定的生命周期回调函数, 做特定的工作 生命周期流程图 生命周期详述 组件的三个生命周期状态: Mount:插入真实 DOM Update:被重新渲染 Unmount:被移出真实 DOM React...(): 后面需要时讲

    22520

    vue核心概念

    1.vue的本质声明式/响应式(寻常的指令)组件化。...(尽可能减少DOM操作(滥杀无辜,只想改变一个列表某一行时,把全部列表重新渲染),不推荐用户直接操作DOM) 4.指令如果有值,这个值是变量(变量必须在组件中可以通过this访问),也可以是表达式(有变量参与的运算...说明:工作中几乎不会用到 动态属性 v-bind给标签动态添加属性,凡是可以使用的属性都可以变成动态的 简写: v-bind:style 简写成:style=‘’ 进阶:使用v-bind实现动态class...,动态style,是非常重要的,在“组件化”时用的非常多 事件绑定 v-on 给标签绑定事件(事件是网页交互的基础) +.可以绑定哪些事件?...在这组兄弟节点中不能插入其他节点 v-else 是不用给‘值’的 v-if和v-show的区别?

    1.2K40

    Vue音乐播放器

    [一] Vue mixins(混合) 作用:为组件定义可复用的方法,可以在 mixin对象 里定义组件的任何属性,在组件使用mixin时,mixin中的属性会添加到组件属性中 http://web.jobbole.com...(2) 冲突 (全局mixin与组件内mixin 中的非钩子函数冲突时,全局mixin被重写) 对于非钩子函数,组件实例的对象属性,组件内的会覆盖全局的。...(3) 实现全局mixin的钩子函数在指定组件中执行/不执行 在时机使用过程中,如果希望钩子函数中的代码只在指定的组件中执行,可以使用组件自定义options来实现( vm....$refs.input2.focus() } [5] 动态组件 和 is属性 通过使用保留的 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换...: is属性 : 用于动态组件且基于 DOM 内模板的限制来工作。

    3K41

    【黄啊码】软件测试之Loadrunner教程

    Each iteration :每次迭代时更新参数的值 ;Each occurrence :每次使用该参数时更新参数的值;Once :执行脚本只取一次值,中途不更新参数的值;当选择取值方式为Unique...,缺少组件时,会弹出窗口显示许安装的组件。...2、在目标函数前插入web_reg_save_param_ex函数,输入左右边界值,需要注意的是边界值中含有“ {等符号时,需要在前面加上转义符\。...3、ctrl+h搜索出目标动态值,并用关联函数进行替换。 4、当边界值筛选出来的是多个动态值时,可以通过关联函数获取所有符合条件的动态值。...2、插入web_reg_save_param_ex函数,输入边界值。需要注意的时,loadrunner12不需要手动添加\进行转义,会自动添加转义符。

    92610

    【黄啊码】软件测试之Loadrunner教程「建议收藏」

    Each iteration :每次迭代时更新参数的值 ; Each occurrence :每次使用该参数时更新参数的值; Once :执行脚本只取一次值,中途不更新参数的值; 当选择取值方式为Unique...,缺少组件时,会弹出窗口显示许安装的组件。...2、在目标函数前插入web_reg_save_param_ex函数,输入左右边界值,需要注意的是边界值中含有“ {等符号时,需要在前面加上转义符\。...3、ctrl+h搜索出目标动态值,并用关联函数进行替换。 4、当边界值筛选出来的是多个动态值时,可以通过关联函数获取所有符合条件的动态值。...2、插入web_reg_save_param_ex函数,输入边界值。需要注意的时,loadrunner12不需要手动添加\进行转义,会自动添加转义符。

    1.6K30

    Vue Slot 与 slot-scope 深入理解

    Slot,中文翻译为插槽,是 Vue.js 提供的一种机制,用于在组件中定义可插入的内容。Slot 允许父组件向子组件传递 DOM 结构,可以将子组件的部分内容进行动态替换。...MyComponent 时,可以向它的 slot 插入内容: 工作原理依然是非常重要的,因为它能够帮助我们更好地理解 Vue 的插槽机制。...当 Vue 编译模板时,会识别出 标签,并将其转化为一个占位符。渲染过程中,Vue 会用父组件传递的内容替换这些占位符。 具体来说,Vue 在编译模板时,会为每个组件生成一个渲染函数。...实战应用 4.1 动态表格组件 我们可以利用 slot 和 slot-scope 创建一个灵活的动态表格组件,使得表格的列定义和内容渲染都由外部控制。 <!

    47910

    Angular Elements 组件在非angular 页面中使用的DEMO

    二、Angular Elements 使用实战      前不久看到项目angular-elements-dashboard :支持动态加载模块和动态加载外部的模块。...其中加载动态外部模块就是先编译一个angular elements项目,然后动态把该bundle.js插入到页面中。...native-shim.js 如果angular elements项目打包时,tsconfig.json中, 编译参数 target: "es5"时,  所有的class都被编译为function,此时就必须引入该文件...当我引入external-dashboard-tile.emulated.js  文件时,它是angular模拟组件的方式插入页面的,就是自定义标签里直接嵌入了div,这种模式并不是真正的Shadow...它的目的是为了不改变Native的模式情况下,引入最新的Shadow Dom v1技术 ,而Native已经过时,不鼓励使用。

    2.7K20
    领券