大佬教程收集整理的这篇文章主要介绍了角度材料2具有ng值访问器的自定义组件,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试实现以下自定义输入
任务:
>设置值为formControl,一旦我从服务器获取数据(data.productTeam是数据 – 可以在代码中看到)
>在编辑时,应使用值更新formcontrol(例如:P12DT2H231M)
问题:
>我无法将默认值绑定到formcontrol.
>没有ngDefaultControl(表单控件的值访问器没有名称:’productTeam’错误发生)
dashboard.component.js
this.CRForm = this.fb.group({ productTeam: [data.productTeam || ''] });
在Dashboard.html中
<mat-form-field floatPlaceholder="always" > <app-mat-custom-form-field #custref formControlName="productTeam" placeholder="P12D" ></app-mat-custom-form-field> <!--<app-mat-custom-form-field #custref formControlName="productTeam" placeholder="P12D" ngDefaultControl></app-mat-custom-form-field> --> </mat-form-field> {{Custref.@R_489_6084@} -- gives value eg:[P12DT1H2M] and only if ngDefaultControl {{CRForm['controls']['productTeam']['value']}} --not giving any
垫定制外形field.ts
import { Component,OnInit,OnDestroy,Input,HostBinding,Optional,Renderer2,Self,forWARDRef,ElementRef } from '@angular/core'; import { MatFormFieldControl } from '@angular/material'; import { ControlValueAccessor,FormGroup,FormBuilder,NgControl,NG_VALUE_ACCESSOR } from '@angular/forms'; import { coerceBooleanProperty } from '@angular/cdk/coercion'; import { FocusMonitor } from '@angular/cdk/a11y'; import { Subject } from 'rxjs/Subject'; class Duration { constructor(public days: number,public hours: number,public minutes: number) {} getDuration() { return 'P' + (this.days || 0) + 'DT' + (this.hours || 0) + 'H' + (this.minutes || 0) + 'M'; } setDuration() {} } @Component({ SELEctor: 'app-mat-custom-form-field',templateUrl: './mat-custom-form-field.component.html',styleUrls: ['./mat-custom-form-field.component.scss'],providers: [{ provide: MatFormFieldControl,useExisTing: MatCustomFormFieldComponent },{ provide: NG_VALUE_ACCESSOR,useExisTing: forWARDRef(() => MatCustomFormFieldComponent),multi: true } ] }) export class MatCustomFormFieldComponent implements OnInit,MatFormFieldControl < Duration >,ControlValueAccessor,OnDestroy { parts: FormGroup; focused = false; stateChanges = new Subject < void > (); errorState = false; controlType = 'my-tel-input'; private _disabled = false; private _required = false; private _placeholder: String; static nextId = 0; @input() get required() { return this._required; } set required(req) { this._required = coerceBooleanProperty(req); this.stateChanges.next(); } @input() get disabled() { return this._disabled; } set disabled(dis) { this._disabled = coerceBooleanProperty(dis); this.stateChanges.next(); } /* code for placeholder property */ @input() get placeholder() { return this._placeholder; } set placeholder(plh) { this._placeholder = plh; this.stateChanges.next(); } @input() get value(): Duration | null { let n = this.parts.value; if (n.days && n.hours && n.minutes) { return new Duration(n.days,n.hours,n.minutes); } return null; } set value(duration: Duration | null) { duration = duration || new Duration(0,0); this.parts.SETVALue({ days: duration.days,hours: duration.hours,minutes: duration.minutes }); this.writeValue('P' + (duration.days || 0) + 'DT' + (duration.hours || 0) + 'H' + (duration.minutes || 0) + 'M'); this.stateChanges.next(); } onContainerClick(event: MouseEvent) { if ((event.target as Element).tagName.toLowerCase() != 'input') { this.elRef.nativeElement.querySELEctor('input').focus(); } } /* code to get id and set id*/ @HostBinding() id = `mat-custom-form- field-${MatCustomFormFieldComponent.nextId++}`; @HostBinding('class.floaTing') get shouldPlaceholderFloat() { return this.focused || !this.empty; } @HostBinding('attr.aria-describedby') describedBy = ''; setDescribedByIds(ids: String[]) { this.describedBy = ids.join(' '); } constructor(fb: FormBuilder,private fm: FocusMonitor,private elRef: ElementRef,renderer: Renderer2,public ngControl: NgControl,) { fm.monitor(elRef.nativeElement,renderer,truE).subscribe(origin => { this.focused = !!origin; this.stateChanges.next(); }); ngControl.valueAccessor = this; this.parts = fb.group({ 'days': '','hours': '','minutes': '',}); } ngOnInit() {} ngOnDestroy() { this.stateChanges.complete(); this.fm.stopMonitoring(this.elRef.nativeElement); } get empty() { let n = this.parts.value; return !n.area && !n.exchange && !n.subscriber; } private propagateChange = (_: any) => {}; public writeValue(a: any) { if (a !== undefined) { this.parts.SETVALue({ days: a.subString(a.lasTindexOf("P") + 1,a.lasTindexOf("D")),hours: a.subString(a.lasTindexOf("T") + 1,a.lasTindexOf("H")),minutes: a.subString(a.lasTindexOf("H") + 1,a.lasTindexOf("M")) }); } }; public registerOnChange(fn: any) { this.propagateChange = fn; } // not used,used for touch input public registerOnTouched() {} // change events from the textarea }
垫定制外形field.html
< div[formGroup]="parts"> < input class="area" formControlName="days" size="3"> < span> & ndash; < /span> < input class="exchange" formControlName="hours" size="3"> < span> & ndash; < /span> < input class="subscriber" formControlName="minutes" size="3"> < /div>
public writeValue(a: String) { if (a && a !== '') { this.parts.SETVALue({ days: a.subString(a.lasTindexOf('P') + 1,a.lasTindexOf('D')),hours: a.subString(a.lasTindexOf('T') + 1,a.lasTindexOf('H')),minutes: a.subString(a.lasTindexOf('H') + 1,a.lasTindexOf('M')) }); } }
表格进行测试
<div> <form #form="ngForm" [formGroup]="productForm"> <mat-form-field> <product-team-input formControlName="productTeam" placeholder="P12D" ></product-team-input> </mat-form-field> </form> {{ form.value | json }} </div>
Simple AppComponent设置控件的默认值(求解点1),还包含一个简单的单击方法,可以模拟从服务器加载数据时的情况.
@Component({ SELEctor: 'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app'; data: String; productForm: FormGroup; constructor(private fb: FormBuilder) { this.productForm = this.fb.group({ productTeam: [null] // can be value like P12DT2H231M as well }); } onClick() { this.productForm.controls['productTeam'].patchValue('P12DT2H231M'); } }
使用此设置,您已经能够使用组件,并且将设置默认值,但您还不会收到任何更改.
为了接收父表单中的更改,您需要使用在组件中注册的propagateChange回调来传播它们(以解决第2点).
因此,组件代码的主要更改是订阅组件内部表单组的更改,您将从中将其传播到上一级:
this.parts = fb.group({ 'days': '',}); this.subs.push(this.parts.valueChanges.subscribe((value: Duration) => { this.propagateChange(value); }));
我还将在这里留下product-team-field.component.ts和Duration类的完整代码,以防万一:
duration.ts
class Duration { constructor(public days: number,public minutes: number) { } toString() { return 'P' + (this.days || 0) + 'DT' + (this.hours || 0) + 'H' + (this.minutes || 0) + 'M'; } }
产品团队field.component.ts
@Component({ SELEctor: 'product-team-input',templateUrl: './product-team-field.component.html',styleUrls: ['./product-team-field.component.css'],providers: [{ provide: MatFormFieldControl,useExisTing: ProductTeamControl },{ provide: NG_VALUE_ACCESSOR,useExisTing: forWARDRef(() => ProductTeamControl),multi: true }] }) export class ProductTeamControl implements OnInit,MatFormFieldControl<Duration> { static nextId = 0; ngControl = null; parts: FormGroup; focused = false; stateChanges = new Subject<void>(); errorState = false; controlType = 'product-team-input'; private _disabled = false; private _required = false; private _placeholder: String; @input() get required() { return this._required; } set required(req) { this._required = coerceBooleanProperty(req); this.stateChanges.next(); } @input() get disabled() { return this._disabled; } set disabled(dis) { this._disabled = coerceBooleanProperty(dis); this.stateChanges.next(); } @input() get placeholder() { return this._placeholder; } set placeholder(plh) { this._placeholder = plh; this.stateChanges.next(); } @input() get value(): Duration | null { const n = this.parts.value; if (n.days && n.hours && n.minutes) { return new Duration(n.days,0); this.writeValue(duration.toString()); this.stateChanges.next(); } onContainerClick(event: MouseEvent) { if ((event.target as Element).tagName.toLowerCase() !== 'input') { this.elRef.nativeElement.querySELEctor('input').focus(); } } @HostBinding() id = `${this.controlTypE}-${ProductTeamControl.nextId++}`; @HostBinding('class.floaTing') get shouldPlaceholderFloat() { return this.focused || !this.empty; } @HostBinding('attr.aria-describedby') describedBy = ''; setDescribedByIds(ids: String[]) { this.describedBy = ids.join(' '); } private subs: Subscription[] = []; constructor( private fb: FormBuilder,private elRef: ElementRef,renderer: Renderer2) { this.subs.push(fm.monitor(elRef.nativeElement,truE).subscribe(origin => { this.focused = !!origin; this.stateChanges.next(); })); this.parts = fb.group({ 'days': '',}); this.subs.push(this.parts.valueChanges.subscribe((value: Duration) => { this.propagateChange(value); })); } ngOnInit() { } ngOnDestroy() { this.stateChanges.complete(); this.subs.forEach(s => S.Unsubscribe()); this.fm.stopMonitoring(this.elRef.nativeElement); } get empty() { const n = this.parts.value; return !n.area && !n.exchange && !n.subscriber; } private propagateChange = (_: any) => { }; public writeValue(a: String) { if (a && a !== '') { this.parts.SETVALue({ days: a.subString(a.lasTindexOf('P') + 1,a.lasTindexOf('M')) }); } } public registerOnChange(fn: any) { this.propagateChange = fn; } public registerOnTouched(fn: any): void { return; } public setDisabledState?(isDisabled: Boolean): void { this.disabled = isDisabled; } }
以上是大佬教程为你收集整理的角度材料2具有ng值访问器的自定义组件全部内容,希望文章能够帮你解决角度材料2具有ng值访问器的自定义组件所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。