2017-04-01 390 views
2

我一直试图在Ionic/Angular2中使用模型表单。我有一个表单,我想要做一些有条件的验证。用户从6个需要的字段开始,然后可以选择“手动”和“自动”处理。如果选择“自动”,则会渲染3个表单输入/选择。我希望这3个字段从不需要的地方变成必需的。尝试使用Angular2表单模型执行条件验证器。尝试使用myForm.setValidators(),但似乎不起作用

这里的模型开始:

this.myForm = this.formBuilder.group({ 
    name: ['', Validators.compose([Validators.required, Validators.maxLength(45), Validators.minLength(2)])], 
    img: [''], 
    longDescription: ['', Validators.compose([Validators.required, Validators.maxLength(200)])], 
    shortDescription: ['', Validators.compose([Validators.required, Validators.maxLength(45)])], 
    processingType: [this.PROCESSING_TYPE.MANUAL], 
    discountType: ['' ], 
    discountRule: ['' ], 
    discountAmount: ['' ], // money, isNumbersOnly handled by custom validator 
    product: [''], 
    dateRuleDays: ['' ], 
    dateRuleTimeStart: ['' ], 
    dateRuleTimeEnd: ['' ], 

    startDate: ['', Validators.required], 
    expiryDate: ['', Validators.required ] 
}); 

discountType,discountRule,discountAmount是3场,我想切换到被要求。

这是我已经试过:

标记,其中setProcessingType FN被调用(如果需要的话我可以提供完整的页面),当用户点击“手动”之间

<!-- automatic or manual --> 
<h4 margin-top text-center>Processing Type</h4> 
<ion-row text-center> 
    <ion-col width-50> 
     <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.MANUAL)" ion-button margin-top>{{ PROCESSING_TYPE.MANUAL }}</button> 
    </ion-col> 
    <ion-col width-50> 
     <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.AUTOMATIC)" ion-button margin-top>{{ PROCESSING_TYPE.AUTOMATIC }}</button> 
    </ion-col> 
</ion-row> 

setProcessingType被称为'自动'按钮。键入:string是我将设置为processingType的新值。

setProcessingType(type: string): void { 

this.myForm.patchValue({ // i welcome comments to correct this to 'setValue()' if needed 
    processingType: type 
}); 

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd']; 
let add = [Validators.required]; 
let empty = []; 

formCtrls.forEach((key, index) => { 
    if (this.myForm.controls && this.myForm.controls[key]) { 
    if (type === this.PROCESSING_TYPE.AUTOMATIC) { 
     this.myForm.controls[key].setValidators([Validators.required]); 
    } else { 
     console.log('resetting validators...'); 
     this.myForm.controls[key].setValidators([]); 
     console.log('errors on : ', key, this.myForm.controls[key].errors); 
    // this.myForm.controls[key].markAsUntouched();  // attempt 3928 
    // this.myForm.controls[key].markAsPristine()  // attempt 3929 
     //this.myForm.controls.updateValueAndValidty(); // this throws an error 
    } 
    } 
}) 

    console.log('new form controls: ', this.myForm.controls); 

}

我还订阅了“processingType” valueChanges这里我跑上面

this.myForm.get('processingType').valueChanges.subscribe(data => this.onProcessingTypeChanged(data)); 

在这里,相同的逻辑功能是从我的值的日志一些截图我试图添加一个验证程序到:

开始(它应该是怎样的)...

点击'自动'后...为什么它们仍然为空?

点击'手动'后...现在他们是必需的? enter image description here

基于上述怀疑,我怀疑

this.myForm.controls.updateValueAndValidty(); 

或 this.myForm.controls [键] .updateValueAndValidity();

是问题,但正如我在代码中所评论的那样,这两者都抛出了“不是函数”的错误。

我已经搜索了几乎所有的条件验证组合,angular2表单模型,动态添加校验器等......太多的链接到这里列出,哈哈。

希望这足以让某人帮助诊断问题。

在此先感谢。

回答

1

更新:2017年4月3日

由于这个post评论,这里的正确答案是明确设置在控制回零误差。

例如:

formCtrls.forEach((key, index) => { 
    if (this.myForm.controls && this.myForm.controls[key]) { 
    if (data === this.PROCESSING_TYPE.AUTOMATIC) 
     this.myForm.controls[key].setValidators([Validators.required]); 
    else { 
     this.myForm.controls[key].validator = []; 
     this.myForm.controls[key].setErrors(null); // CORRECT WAY- NOW VALIDATORS ARE GONE AND ERRORS ARE NULL 
    } 
    } 
}) 

OLD答案

看来,我固定的问题,但我不舒服。感觉像:

1.)我错过了明显的正确方法来做到这一点。

2.)这是一个巨大的黑客攻击。

3.)这是一个错误(我非常怀疑这个 - 我通常认为我在这种情况下是错误的)。通过控制循环和使用setValidators()实际上工作,我只是没有意识到它,直到我试过@ Sampath的答案上面(其工作方式与setValidators()相同,但没有解决问题) 。

为了解决这个问题,每当valueChanges观察者的回调被触发时,我明确地将每个输入的值设置为一个空字符串。

的代码:

onProcessingTypeChanged(data) { 

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd']; 
let add = [Validators.required]; 
let empty = []; 
let newValue; 

if (data === this.PROCESSING_TYPE.AUTOMATIC) newValue = ""; 
else newValue = " "; // SET TO AN EMPTY STRING 

this.myForm.patchValue({ 
    discountType: newValue, 
    discountRule: newValue, 
    discountAmount: newValue, 
    product: newValue, 
    dateRuleDays: newValue, 
    dateRuleTimeStart: newValue, 
    dateRuleTimeEnd: newValue, 
}); 


formCtrls.forEach((key, index) => { 
    if (this.myForm.controls && this.myForm.controls[key]) { 
    if (data === this.PROCESSING_TYPE.AUTOMATIC) 
     this.myForm.controls[key].setValidators([Validators.required]); 
    else 
     this.myForm.controls[key].setValidators([]); 
    } 
}) 

}

探索好位之后,它似乎(myForm.controls [键] .errors)正在内部处理针对此返回闭合的错误:

function(control) { 
    return isEmptyInput(control.value) : { 'required': true } ? null; 
} 

所以,在我所知,每个值不进行重置为空字符串(我觉得奇怪,b/C空字符串是falsy,但在关闭它通过为不拜因g为空输入),angular将每个输入注册为空,并将错误对象设置为{required:true},因此即使在每个输入上没有必需的验证器,也将表单注册为仍然无效。

不会将此标记为正确的 - 如果有人纠正了此逻辑或存在类似问题,将会对此反馈感到满意。