angular - Angular:动态表单的问题
问题描述
我有一个我想要动态的子表单,即一个选择字段值更改另一个选择字段的内容并设置默认值(如果存在)。
依赖选择选项发生了很大变化,但修补默认值不起作用......
这是.ts:
export interface GsmattFormValues {
id: number,
mattype: number,
material: number,
}
@Component({
selector: 'ngx-gsmatt',
templateUrl: './gsmatt.component.html',
styleUrls: ['./gsmatt.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => GsmattComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => GsmattComponent),
multi: true
}
]
})
export class GsmattComponent implements OnInit, OnDestroy, ControlValueAccessor {
@Input() inMandatoryObjects: any;
@Input() inErrors: any[];
mattypes: Mattype[];
materials: Material[];
allowMaterials: boolean = false;
destroy$: Subject<boolean> = new Subject<boolean>();
gsmattForm: FormGroup;
constructor(
private formBuilder: FormBuilder,
public translate: TranslateService,
) {
}
get f() { return this.gsmattForm.controls; }
/////////////////////////////////////////////////////////
////// OnInit & onDestroy
/////////////////////////////////////////////////////////
ngOnInit(): void {
this.mattypes=this.inMandatoryObjects['mattypes'];
this.materials=this.inMandatoryObjects['materials'];
this.initForm();
this.gsmattForm.valueChanges.takeUntil(this.destroy$).subscribe(value => {
this.onChange(value);
this.onTouched();
});
}
ngOnDestroy() {
this.destroy$.next(true);
this.destroy$.unsubscribe();
}
//////////////////////////////////////////////////////////////////////////////
///// Control Value Accessor
//////////////////////////////////////////////////////////////////////////////
get value(): GsmattFormValues {
return this.gsmattForm.value;
}
set value(value: GsmattFormValues) {
//if( value !== undefined && this.value !== value){
if( value !== undefined ){
this.configureMatRCP(this.mattypes.find(item => item.id==value.mattype));
this.gsmattForm.patchValue(value);
this.onChange(value);
this.onTouched();
}
}
onChange: any = () => {}
onTouched: any = () => {
}
// this method sets the value programmatically
writeValue(value) {
if (value) {
this.value = value;
}
if (value === null) {
this.gsmattForm.reset();
}
}
// upon UI element value changes, this method gets triggered
registerOnChange(fn) {
this.onChange = fn;
}
// upon touching the element, this method gets triggered
registerOnTouched(fn) {
this.onTouched = fn;
}
// communicate the inner form validation to the parent form
validate(_: FormControl) {
return this.gsmattForm.valid ? null : { profile: { valid: false } };
}
get errors() {
return this.gsmattForm.errors ? null : this.gsmattForm.errors;
}
//////////////////////////////////////////////////////////////////////////////
///// Miscellaneous Functions
//////////////////////////////////////////////////////////////////////////////
initForm() {
this.gsmattForm = this.formBuilder.group({
id: '',
mattype: new FormControl('', [Validators.required, SelectedValue]),
material: new FormControl(''),
});
}
/////////////////////////////////////////////////////////
////// Event Functions
/////////////////////////////////////////////////////////
onMattypeChange(event) {
var MATP;
if (event) {MATP=this.mattypes.find(item => item.id==event);}
console.log("UPDATING");
this.configureMatRCP(MATP);
this.setDfltValues(MATP);
}
/////////////////////////////////////////////////////////
////// Dynamic Form Functions
/////////////////////////////////////////////////////////
configureMatRCP(mattype?: Mattype) {
console.log("FOrm "+JSON.stringify(this.gsmattForm.value));
if (mattype) {
this.materials=this.inMandatoryObjects['materials'].filter(item => item.mattype.id==mattype.id);
if (this.materials.length>0) {
this.gsmattForm.get("material").enable();
this.allowMaterials=true;
}
else {
this.gsmattForm.get("material").disable();
this.allowMaterials=false;
}
}
else {
this.allowMaterials=false;
this.gsmattForm.get("material").disable();
}
}
setDfltValues(mattype?: Mattype) {
if (mattype) {
var materialsTmp=this.inMandatoryObjects['materials'].filter(item => item.mattype.id==mattype.id);
if (materialsTmp.length>0) {
var dfltMaterial = materialsTmp.find(item => item.isdefault==true);
console.log("DFLMATERIAL "+JSON.stringify(dfltMaterial));
if (dfltMaterial) {console.log("BOOM "+dfltMaterial.id);
this.gsmattForm.patchValue({material: dfltMaterial.id});
}
else {this.gsmattForm.patchValue({material: ''});}
}
else {
this.gsmattForm.patchValue({material: ''});
}
}
else {
this.gsmattForm.patchValue({material: ''});
}
}
}
和html:
<div class="row">
<div class="col-md-12">
<nb-card>
<nb-card-body>
<div [formGroup]="gsmattForm">
<input type="hidden" nbInput fullWidth id="id" formControlName="id"/>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="mattype" class="label">{{ 'MATTYPE' | translate }}</label>
<nb-select id="mattype" formControlName="mattype" fullWidth status="basic"
placeholder="{{ 'MATTYPE' | translate }}" (selectedChange)="onMattypeChange($event)">
<nb-option *ngFor="let option of mattypes" [value]="option.id">
{{ option.label | translate }}
</nb-option>
</nb-select>
<div *ngIf="f.mattype.touched && f.mattype.errors" class="invalid-feedback d-block">
<div *ngIf="f.mattype.errors['required']">{{ 'FIELD_REQUIRED' | translate: {field: 'MATTYPE' | translate} }}</div>
</div>
</div>
</div>
<div class="col-sm-6" *ngIf="allowMaterials">
<div class="form-group" >
<label for="material" class="label">{{ 'MATERIAL' | translate }}</label>
<nb-select id="material" formControlName="material" fullWidth status="{{ (f.material.errors && f.material.touched) ? 'danger': (!f.material.errors && f.material.touched) ? 'success' : 'basic' }}"
placeholder="{{ 'MATERIAL' | translate }}">
<nb-option *ngFor="let option of materials" [value]="option.id">
{{ option.label | translate }}
</nb-option>
</nb-select>
<div *ngIf="f.material.touched && f.material.errors" class="invalid-feedback d-block">
<div *ngIf="f.material.errors['required']">{{ 'FIELD_REQUIRED' | translate: {field: 'MATERIAL' | translate} }}</div>
</div>
</div>
</div>
</div>
</div>
</nb-card-body>
</nb-card>
</div>
</div>
谢谢您的帮助
编辑 1:经过大量购买后,选择选项过滤和修补值之间似乎存在冲突。然后我尝试使用回调确保在设置值之前等待选择选项更新。
configureMatRCP(setDfltValue: boolean, callback, mattype?: Mattype) {
console.log("FOrm "+JSON.stringify(this.gsmattForm.value));
if (mattype) {
this.materials=this.inMandatoryObjects['materials'].filter(item => item.mattype.id==mattype.id);
if (this.materials.length>0) {
this.gsmattForm.get("material").enable();
this.allowMaterials=true;
}
else {
this.gsmattForm.get("material").disable();
this.allowMaterials=false;
}
}
else {
this.allowMaterials=false;
this.gsmattForm.get("material").disable();
}
if(setDfltValue) {
callback(mattype);
}
}
和
onMattypeChange(event) {
var MATP;
if (event) {MATP=this.mattypes.find(item => item.id==event);}
console.log("UPDATING");
this.configureMatRCP(true, this.setDfltValues(MATP), MATP);
//this.setDfltValues(MATP);
}
但我得到错误回调不是函数......我错过了什么?
解决方案
推荐阅读
- python - 如何在不中断正在运行的进程的情况下异步处理不同的(通过前端请求的)任务?
- java - 带有 SQL 组件的 Apache Camel 用于批处理 = true 的插入会在多个表中引发错误
- python-3.x - Sigkill 错误:在自定义数据集上训练 Mask RCNN 模型
- java - spring 到 spring boot 2.4.5 迁移:无法从 UI 的 Ajax 调用中的 spring 控制器发送 ModelAndView
- c# - 尝试统一制作一个简单的Tag游戏
- php - Wordpress 数据库没有更新
- javascript - 节目
只有当点击 , 考虑到我们有很多 元素 - powershell - 每个路由器的第二个箭头
- python - Python PyQt5 - 可折叠框 - 将图形添加到默认折叠框会导致图形大小错误
- websocket - WebSockets 的哪些子协议在 ATM 上可用?