éä¿¡ããŠããŸã... ïŒãxãã§ãã§ãã¯ããŠãã ããïŒ
[ ] bug report => search github for a similar issue or PR before submitting
[x] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
çŸåšã®åäœ
TypeScript FormBuilderãä»ããReactiveFormã«ïŒrequiredãmaxLengthïŒã®ãããªåºæ¬çãªããªããŒã¿ãŒãåããAbstractControlããããŸãã ãããã®åºæ¬çãªããªããŒã¿ãŒã«ãããããããŠã³å€ã«åºã¥ããŠæ€èšŒæŠç¥ãåçã«å€æŽããã«ã¹ã¿ã ããªããŒã¿ãŒãè¿œå ããŸããã çŸåšãå¥ã®ã³ã³ããŒãã³ãå
setValidators()
ã¡ãœããã䜿çšããŠããŸãïŒAbstractControlã¯@Input()
ãä»ããŠå«ãŸããŠããŸãïŒã äž»ãªåé¡ã¯ãæ¢åã®ããªããŒã¿ãŒãäžæžãããããšã§ãã
äŸïŒ
ã¢ããªã³ã³ããŒãã³ã
this.formBuilder.group({
zip: ['', [Validators.required, Validators.maxLength(10)]]
});
ã¢ããªãã³ãã¬ãŒã
<zip ...
[control]="form.controls.zip">
</zip>
ZIPã³ã³ããŒãã³ã
@Input() control: AbstractControl;
this.control.setValidators([
// redundant to formBuilder
Validators.required,
Validators.maxLength(10),
// custom validation based on a dropdown value (via. valueChange Detection)
validateZipFn(countryCode)]
);
äºæ³ãããè¡å
æè»æ§ãç¶æããããã«ããã¹ãŠã®ããªããŒã¿ãŒãäžæžãããããããŸããã 以äžã®ã³ãŒãã¯ã getValidators()
ã¡ãœããã®åäœã瀺ããŠããŸãã
ã¢ããªã³ã³ããŒãã³ã
this.formBuilder.group({
zip: ['', [Validators.required, Validators.maxLength(10)]]
});
ã¢ããªãã³ãã¬ãŒã
<zip ...
[control]="form.controls.zip">
</zip>
ZIPã³ã³ããŒãã³ã
@Input() control: AbstractControl;
let listOfAllValidationRules = this.control.getValidators().push(validateZipFn(countryCode)]);
this.control.setValidators(listOfAllValidationRules);
è¡åãå€ããåæ©/ãŠãŒã¹ã±ãŒã¹ã¯äœã§ããïŒ
åçæ€èšŒã«ããæè»ã«ãªããŸãã
AngularããŒãžã§ã³ïŒ ã2.1.2
ãã©ãŠã¶ïŒãã¹ãŠ
èšèªïŒ TypeScript / ES6
@Icepickè¿ããã®ã¯äœããããŸããã ããªããŒã¿ãŒã¯ãé åã§ã¯ãªãåäžã®ãªããžã§ã¯ããšããŠæ ŒçŽãããŸãã
@DzmitryShylovichããã¯å®è£ ã§ããªããšããæå³ã§ããïŒ å人çã«ã¯ãã¡ã¿ããŒã¿ãæ·»ä»ãããããªããŒã¿ãŒã®èªã¿åãå°çšã³ããŒã®ã¿ãå¿ èŠã§ãã
æ€èšŒã¡ãã»ãŒãžã®ãªããžã§ã¯ããæž¡ããããã£ã¬ã¯ãã£ããäœæããŠããŸããããã¯ãæ€èšŒã«ãŒã«åãããŒã§ãå€ã衚瀺ãããã¡ãã»ãŒãžã§ãããªããžã§ã¯ãã§ãã ãã®ãªããžã§ã¯ããšNgControlã®ã»ããããªããŒã¿ãŒãæ¯èŒããŠãç¹å®ã®ã¡ãã»ãŒãžãæ¬ èœããŠããå Žåã«ãŠãŒã¶ãŒã«èŠåããããã«ããŸãã
@Bidthedogãšåæ§ã®çç±ã§ãããèŠããã§ãã ããšãã°ã Validator.requried
ãã³ã³ãããŒã«äžã«ããå Žåããããããã°ã©ã ã§ãã©ãŒã ã«ç€ºããŸãã å¿
èŠãªã®ã¯èªã¿åãå°çšã§ãã çŸåšç§ãã§ããæåã®ããšã¯ãã³ã³ããŒãã³ãã«é
åãå®çŸ©ããããããã©ãŒã ã³ã³ãããŒã«å®çŸ©ã«æž¡ãããšã§ãã ããã¯ããªãããã«éããªãã§ãããïŒ
ããã¯ããŒããããã«ãããŸããïŒããå Žåããã®æ©èœã«ETAã¯ãããŸããïŒ
ãã®éãã ç§ã®ãã©ãŒã ãµãŒãã¹ã«ã¯ãåºæ¬çã«3ã€ã®å€§ããªåä»ãªéè€å®çŸ©ããããŸãã 以äžã®ã³ãŒãã¹ããããã¯ãç§ããŸãšããŠããããªã倧ããª6ããŒãžã®ãã©ãŒã ããã®å°ããªæç²ã§ãã ããã¯ã1ããŒãžç®ïŒè©³çŽ°ïŒãš2ããŒãžç®ïŒå»çïŒã®å§ãŸãã§ãã
äœæ/å®çŸ©ããã«ã¯ïŒ
private createForm() {
this.form = this.fb.group({
details: this.fb.group({
NHSNumber: [null, [Validators.required, Validators.pattern(/^\d{3}-\d{3}-\d{4}$/)]],
titleId: [null, [Validators.required]],
firstName: [null, [Validators.required, Validators.maxLength(10)]],
middleNames: null,
lastName: [null, [Validators.required]],
DOB: [null, [Validators.required]],
genderId: [null, [Validators.required]],
regionId: [null, [Validators.required]],
maritalStatusId: [null, [Validators.required]],
occupationTypeId: [null],
occupationId: null,
telephoneNo: null,
mobileNo: null,
houseNumber: null,
streetName: null,
town: null,
city: null,
county: null,
postcode: null,
GPId: null,
nextOfKinId: null,
livesWith: null
//vehicleLicenseTypeId?: number[]
}),
medical: this.fb.group({
gpId: [null, [Validators.required]]
})
});
}
ç§»å ¥ããã«ã¯ïŒ
private populateForm() {
let m = this.model;
this.form.setValue({
details: {
NHSNumber: this.getTextValue(m.NHSNumber),
titleId: this.getLookupValue(m.titleId),
firstName: this.getTextValue(m.firstName),
middleNames: this.getTextValue(m.middleNames),
lastName: this.getTextValue(m.lastName),
DOB: this.getDateValue(m.DOB),
genderId: this.getLookupValue(m.genderId),
regionId: this.getLookupValue(m.regionId),
maritalStatusId: this.getLookupValue(m.maritalStatusId),
occupationTypeId: this.getLookupValue(m.occupationTypeId),
occupationId: this.getLookupValue(m.occupationId),
telephoneNo: this.getTextValue(m.telephoneNo),
mobileNo: this.getTextValue(m.mobileNo),
houseNumber: this.getTextValue(m.houseNumber),
streetName: this.getTextValue(m.streetName),
town: this.getTextValue(m.town),
city: this.getTextValue(m.city),
county: this.getTextValue(m.county),
postcode: this.getTextValue(m.postcode),
GPId: this.getLookupValue(m.GPId),
nextOfKinId: this.getLookupValue(m.nextOfKinId),
livesWith: this.getTextValue(m.livesWith)
},
medical: {
gpId: this.getLookupValue(m.GPId) || 1
}
});
æ€èšŒã«ãŒã«ã å®å šã§ã¯ãããŸãããããããã©ã®ããã«ä¹±éã«ãªããéããªãããããããŸã
private formValidationMessages = {
details: {
NHSNumber: {
required: '\'NHS Number\' is required',
pattern: '\'NHS Number\' must be in the format \'NNN-NNN-NNNN\' where N is a digit'
},
titleId: {
required: '\'Title\' is required'
},
firstName: {
required: '\'First Name\' is required'
}
},
medical: {
}
};
ç§ã¯1ã€ã®ãªããžã§ã¯ãã»ããã§ãã¹ãŠã®ãã©ãŒã ã«ãŒã«ãå®çŸ©ããäœæ¥ãéå§ããŸãããããã¯ãäžèšã®é¢æ°ãç¹°ãè¿ãåŠç/æ圱ããããšãèããŠããŸãïŒãŸã ããã»ã©é²ãã§ããŸãããïŒã
private formValidationMessages = {
details: {
NHSNumber: {
required: '\'NHS Number\' is required',
pattern: '\'NHS Number\' must be in the format \'NNN-NNN-NNNN\' where N is a digit'
},
titleId: {
required: '\'Title\' is required'
},
firstName: {
required: '\'First Name\' is required'
}
},
medical: {
}
};
ãã¡ãããããã«å ããŠãããŒã¿ã¢ãã«ã®å®çŸ©ãããã次ã«ããã¯ãšã³ãã®ãã¹ãŠã®ã¬ã€ã€ãŒããããŸãã ã³ãŒãã®èšåŒµãæžããããã«ç§ãã¡ã«ã§ããããšãããã¯ãã§ããïŒ
ãŸããFormControlçšã«æ§æãããããªããŒã¿ãŒãååŸã§ããªãããšã«ãèŠèãããŸããã
FormBuilderã«æž¡ãããåã«æ§æãªããžã§ã¯ããã©ããããã³ã³ãããŒã«åãšæå®ãããããªããŒã¿ãŒã®éã®ãããã³ã°ã远跡ãããŠãŒãã£ãªãã£ãµãŒãã¹ãè¿œå ããããšã§ããã®åé¡ãåé¿ããŸããã
ãã®è¿œå ãµãŒãã¹ã®å¿ èŠæ§ãåãé€ãããšã¯åœç¶çŽ æŽãããããšã§ãð
ããã«æçš¿ããŠããããã¹ãŠã®ãã©ãŒã æ§æã1ã€ã®å€§ããªãªããžã§ã¯ãã«çµ±åããæ§æã«åºã¥ããŠãã©ãŒã ãšã¢ãã«éã®ãããã³ã°ãè¡ãããã€ãã®ãã«ããŒã¡ãœãããäœæããŸããã ããã¯ãã¹ãŠããŸãã«ãè€éã«æããŸãããããã¯ç§ãæã£ãŠããåŠç¿æ²ç·ã§ããå¯èœæ§ããããŸãã
ããã«ã¡ã¯ã
ãã®æ©èœã«ã€ããŠäœãèšèããããã©ããçåã«æã£ãŠããŸãã ç¹å®ã®ã¢ã€ãã ãå¿
èŠã«å¿ããŠèŠèŠçã«ããŒã¯ã§ããããšã¯ãææ°ã®ãã©ãŒã UIã«æåŸ
ãããåºæ¬çãªæ©èœã®ããã«æããŸãã ãã ãããã£ãŒã«ããå¿
é ãã©ããã«é¢ä¿ãªãæ
å ±ãååŸããæ¹æ³ããªãããããªã¢ã¯ãã£ããã©ãŒã ã䜿çšããŠãã®æ©èœãå®è£
ããããšã¯ã§ããŸããã
ããã¯äžå¯èœã§ã¯ãããŸãããããã¯ãã ããããã®ä»äºã§ãã
@Bidthegodã¯ããã®æ©èœãAngularã§å®è£ ããã®ã¯å€§å€ãªäœæ¥ã«ãªãã®ã§ããããããããšãAngularã³ã³ããŒãã³ãã§ããªããŒã¿ãŒãååŸããã®ã¯å€§å€ãªäœæ¥ã«ãªãã®ã§ããããã
ã³ã³ããŒãã³ãå ã®ããªããŒã¿ãŒãååŸã§ããå Žåã¯ããã®æ¹æ³ã«é¢ããå ¥åãæè¿ããŸãã
ãŸãã¯ãç¹å®ã®ã³ã³ããŒãã³ãã¿ã€ãïŒå ¥åãéžæïŒã®æ¹ãç°¡åãªå Žåã¯ãããã圹ç«ã¡ãŸãã
@Toubç§ããã£ãããšã¯ããã¹ãŠã®åã ã®ãã©ãŒã ãã£ãŒã«ããšãã®ãã¹ãŠã®èšå®ïŒè¡šç€ºãããªããŒã¿ãŒãã«ãŒã«ãªã©ïŒãå«ããconfigããªããžã§ã¯ãæ§é ãæ§ç¯ããããšã§ããã 次ã«ãFormGroupãæ§ç¯ããæ§æãç §äŒããããã®ããã€ãã®ãã«ããŒã¡ãœãããäœæããŸããã åãã©ãŒã ã«ã¯ãã©ãŒã ãµãŒãã¹ããããåºæ¬ã³ã³ããŒãã³ãããç¶æ¿ããŸãã
ç°¡åãªä¿®æ£ãšã¯èšããŸãããã倧éã®ã³ãŒãããããŸãããããªããšã¬ã¬ã³ãã§ãããªãè€éãªãã©ãŒã ãç°¡åã«äœæã§ããããã«ãªããŸããã ããªããèŠãããã«èŠç¹ã§ã³ãŒãã®ããã€ããæããŸããããããç§ã¯ä»ã®ãšãããããé©åã«ã¢ãžã¥ãŒã«åããæéããããŸããã ç§ãæžãããã¹ãŠã®ã«ã¹ã¿ã ãã©ãŒã å ¥åã³ã³ããŒãã³ããå«ããããã«ã¯ããªãã®æ°ã®ãã¡ã€ã«ããããŸããã
https://gist.github.com/Bidthedog/1dc7d10cda1759061c09f44f7b48cbf3
@Bidthedogããã¯ç§ã®ããŒãºã«å¿ããŸããããèŠç¹ã¯ä»ã®äººã«ã圹ç«ã€ã®ã§ãããªãã®çãã«æè¬ããŸãã
ããã¿ããªãç§ã¯ããªããŒã¿ãŒãè¿ãããã®ç°¡åãªãã«ããŒãäœæããŸããïŒå¿ èŠãªã ãã§ãããä»ã®äººã®ããã«æ¡åŒµããããšãã§ããŸãïŒïŒ
getValidators(_f) {
return Object.keys(_f).reduce((a, b) => {
const v = _f[b][1];
if (v && (v === Validators.required || v.indexOf(Validators.required) > -1)) {
if (!a[b]) { a[b] = {}; }
a[b]['required'] = true;
}
return a;
}, {});
}
const _f = {
id: [],
name: [null, Validators.required],
phone: [],
email: [null, [Validators.required, Validators.email]]
};
this.frmMain = this._fb.group(_f);
console.log(this.getValidators(_f)); // {name: {"required": true}, email: {"required": true}}
ç§ã®ããŒãºã«åããŸãð
ç§ã¯åæããŸããçŸåšã®ã³ã³ãããŒã«ã®ã¡ãœããã§ååŸã§ããããªããŒã¿ãŒã®èªã¿åãå°çšãªã¹ãããããšéåžžã«åœ¹ç«ã¡ãŸãã
ãã®æ©èœã®+1
èªã¿åãå°çšãªã¹ãã®å Žåã¯+1
+1
ãã§ã«ååšããããªããŒã¿ãŒã倱ãããšãªãåçã«ããªããŒã¿ãŒãè¿œå ããã«ã¯ããã®æ©èœãå¿
èŠã§ãã äœãã®ãããªãã®ïŒ
Object.keys(this.myForm.controls).forEach(key => {
if (map.get(key)) {
this.myForm.get(key).setValidators(this.myForm.get(key).getValidators().push(Validators.required))
}
});
å®å
šã«èª¬æãããŠããïŒ https ïŒ//stackoverflow.com/questions/46852063/how-to-dynamically-add-validators-to-the-forms-in-angular-2-4-using-formbuildeã
ããã¯äžè¬çãªãã®ã§ãªããã°ãªããŸãã
å®éãcomposeValidatorsïŒhttps://github.com/angular/angular/blob/master/packages/forms/src/directives/shared.ts#L139ïŒã䜿çšããŠããªããŒã¿ãŒãåçã«è¿œå ããããšã¯ããã»ã©é£ãããããŸããã ããªããŒã¿ãŒã®åé€ããã倧ããªåé¡ã ãšæããŸãã ããŒã«å€ã§ãããè¡ãããšãã§ããŸãããããªããŒã¿ãŒã¯ãã¯ãçŽç²é¢æ°ã§ã¯ãããŸããã
ãã®é¢æ°ã¯ãFormGroupsããã³FormControlsã§æ©èœããŠãå¿ èŠãªããªããŒã¿ãŒã決å®ããå¿ èŠããããŸã
export const hasRequiredField = (abstractControl: AbstractControl): boolean => {
if (abstractControl.validator) {
const validator = abstractControl.validator({}as AbstractControl);
if (validator && validator.required) {
return true;
}
}
if (abstractControl['controls']) {
for (const controlName in abstractControl['controls']) {
if (abstractControl['controls'][controlName]) {
if (hasRequiredField(abstractControl['controls'][controlName])) {
return true;
}
}
}
}
return false;
};
@mtinnerããã¯æ¬åœã«çŽ æŽãããçºèŠã§ããã ããã¯ç§ã«åæã»ãããååŸããŠããŸãã ãªãã¶ãŒããã«ã®ããªããŒã¿ãŒãè¿ãããšãã§ããããã«ãAPIã«è¿œå ãã䟡å€ã¯ãŸã ãããšæããŸãã ããããã°ãæ¡ä»¶ä»ãã®å¿ é ã³ã³ãããŒã«ãèŠã€ããã®ã¯éåžžã«ç°¡åã§ãã ããã§ææ¡ãããŠããåé¿çãé©çšããŠããããã®ã€ã³ã¹ã¿ã³ã¹ããã£ããã§ãããã©ããã¯ããããŸããã
Angular Connect 2017ã®éåžžã«çŽ æŽããããã¬ãŒã³ããŒã·ã§ã³ã§ã @ karaã¯ãã«ã¹ã¿ã ãã©ãŒã ã³ã³ãããŒã«ã¯çŽ æŽããããæããªãããšèšã£ãŠçµäºããŸãã è¯ãã§ãããã«ã¹ã¿ã ã³ã³ãããŒã«ã®ãã®éèŠãªæ©èœããããŸãã
+1
PRã®æéã¯ãããŸãããããããç§ãæãã€ãããã®ã§ãïŒ
import {FormControl} from '@angular/forms';
import {AsyncValidatorFn, ValidatorFn} from '@angular/forms/src/directives/validators';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';
import {AbstractControlOptions} from '@angular/forms/src/model';
export class DescendingFormControl extends FormControl {
private asyncValidationChangesSubject = new Subject<AsyncValidatorFn | AsyncValidatorFn[]>();
private validationChangesSubject = new Subject<ValidatorFn | ValidatorFn[] | null>();
public readonly validationChanges: Observable<ValidatorFn | ValidatorFn[] | null>;
public readonly asyncValidationChanges: Observable<AsyncValidatorFn | AsyncValidatorFn[]>;
constructor(formState?: any, validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null, asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null) {
super(formState, validatorOrOpts, asyncValidator);
this.validationChanges = this.validationChangesSubject.asObservable();
this.asyncValidationChanges = this.asyncValidationChangesSubject.asObservable();
}
public setValidators(newValidator: ValidatorFn | ValidatorFn[] | null): void {
super.setValidators(newValidator);
this.validationChangesSubject.next(newValidator);
}
public setAsyncValidators(newValidator: AsyncValidatorFn | AsyncValidatorFn[]): void {
super.setAsyncValidators(newValidator);
this.asyncValidationChangesSubject.next(newValidator);
}
}
ç§ãèªç±ãªæéãåŸãåã«èª°ããPRã®ä»äºå šäœãããããšããŠãããªããããã®ããã«è¡ã£ãŠãã ããïŒ
+1
+1
+1
çŸåšã®ããªããŒã¿ãŒã®é
åã¯ååšããŸãããç§ãã¡ã«ã¯å©çšã§ããŸãã...
ããªããŒã¿ãŒã®éçã¡ãœããcompose
ãèŠãŠãã ãããããã¯ããã©ãŒã ã³ã³ãããŒã«ã§ããªããŒã¿ãŒã®é
åãå®çŸ©ãããšãã«èå°è£ã§äœ¿çšãããã¡ãœããã§ãã
static compose(validators: (ValidatorFn|null|undefined)[]|null): ValidatorFn|null {
if (!validators) return null;
// Here it is
const presentValidators: ValidatorFn[] = validators.filter(isPresent) as any;
if (presentValidators.length == 0) return null;
return function(control: AbstractControl) {
return _mergeErrors(_executeValidators(control, presentValidators));
};
}
https://github.com/angular/angular/blob/master/packages/forms/src/validators.ts#L342
ã芧ã®ãšããã presentValidators
ã¯ç§ãã¡ãæ¢ããŠãããã®ã§ãããã¯ããŒãžã£ã«_ãã©ãã_ãããŠããããã¢ã¯ã»ã¹ã§ããã compose
ããååŸããå€ã®ã¿ããããªã¬ãŒããããã¹ãŠã®ãšã©ãŒãå«ããªããžã§ã¯ãã§ããäžããããå€ã
ãããã£ãŠãããªããŒã¿ãŒãæšæž¬ããå¯äžã®æ¹æ³ã¯ããã©ãŒã ã³ã³ãããŒã«ã§ãšã©ãŒãæåã§ããªã¬ãŒããããšã§ããããã«ãããããªããŒã¿ãŒã®ååãåç
§ãããŸãã
ãã€ã³ãããããã©ãŒã ã³ã³ãããŒã«ã§ãšã©ãŒãããªã¬ãŒããããªãã 代ããã«ããã³ãã¬ãŒããžã®ãã€ã³ãããªãæ°ãããã©ãŒã ã³ã³ãããŒã«ãäœæããåãValidatoré¢æ°ãé©çšããŠãããå€ãèšå®ããŠå¿ èŠãªãšã©ãŒãããªã¬ãŒããå¿ èŠããããŸãã
// Your form control, actually binded to a form in your template
emailControl = new FormControl('', [Validators.required, Validators.email])
// Elsewhere in your code
// You use dummy form controls, on which you apply your original form control validators and various values, to trigger the errors.
const errorsWhenEmpty = new FormControl('', this.emailControl.validator, this.emailControl.asyncValidator).errors
const errorsWhenOneChar = new FormControl('x', this.emailControl.validator, this.emailControl.asyncValidator).errors
// Or you can simply reuse the first dummy control with `setValue()`
çæ³ããã¯ã»ã©é ãã§ãããããªããŒã¿ãŒèªäœãæã«å ¥ããããšãã§ãããŸã§ã¯ãç§ãèŠã€ããäžã§æãæ±ãæ¹æ³ã§ã¯ãããŸããã
FormControlã¯ã©ã¹ããæ¡åŒµããåã¯ã©ã¹ã®ãã£ãŒã«ãã«ãã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããValidatoré¢æ°ã®ã³ããŒãä¿åããããšããå§ãããŸãã次ã®ããã«ãªããŸãã
export class ExtFormControl extends FormControl {
private _syncValidators: ValidatorFn | ValidatorFn[];
private _asyncValidators: AsyncValidatorFn | AsyncValidatorFn[];
constructor(formState?: any, validatorOrOpts?: ValidatorFn | ValidatorFn[] | null,
asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null) {
super(formState, validatorOrOpts, asyncValidators);
this._syncValidators = validatorOrOpts;
this._asyncValidators = asyncValidators;
}
getSyncValidators(): ValidatorFn[] {
if (typeof this._syncValidators === 'function') {
return [this._syncValidators];
} else {
return this._syncValidators;
}
}
getAsyncValidators(): AsyncValidatorFn[] {
if (typeof this._asyncValidators === 'function') {
return [this._asyncValidators];
} else {
return this._asyncValidators;
}
}
setValidators(newValidator: ValidatorFn | ValidatorFn[] | null): void {
super.setValidators(newValidator);
this._syncValidators = newValidator;
}
setAsyncValidators(newValidator: AsyncValidatorFn | AsyncValidatorFn[] | null): void {
super.setAsyncValidators(newValidator);
this._asyncValidators = newValidator;
}
}
ç§ã¯ãã¹ãŠãããªããŒã¿ãŒã®èªã¿åãå°çšãªã¹ããæ±ããŠããŸãã ReactiveFormsã䜿çšããŠããã³ãã¬ãŒãã§ã¯ãªãFormBuilderã³ãŒããä»ããŠmaxLengthãªã©ã®å¶çŽãæ§æããããšãæåŸ ãããå ŽåããããŸãã ãã ããçŸåšãããã€ãã®åäœïŒãã©ãŒã«ã¹ã次ã®ãã£ãŒã«ãã«ç§»åãããã¯ã¬ãžããã«ãŒãå ¥åã®äžè¬çãªã±ãŒã¹ãªã©ïŒãå®çŸ©ããããå¿ èŠã«å¿ããŠã©ãã«ãèªåçã«ããŒã¯ãããããããã«ãHTMLã«maxlengthãé 眮ããå¿ èŠããããŸãã
ãã©ãŒã ã«å ¥åããããšæŽæ°ãããããªããŒã¿ãŒãããã°ã©ã ã§èšå®ããå¿ èŠããããŸããFormControlã§ããªããŒã¿ãŒãèªã¿åãããšéåžžã«äŸ¿å©ã§ãã ç§ã¯@moniuchã«åæããŸããReactiveFormsã䜿çšãããšããããå¯èœã«ãªããšæåŸ ãããŸãã ãããå®è£ ãããããšãé¡ã£ãŠããŸãã
æŽæ°ã¯ãããŸããïŒ
ããŒãã 1985幎ã«ãã®ååç©ãèå³æ·±ãåé¡ã ãšæã£ãŠããŸã1
ã»ãããããããªããŒã¿ãŒã確èªããããåªå
é äœãä»ãããããããšã¯ã§ããŸããã :(
ã³ã³ãããŒã«ã®ãvalidatorãããããã£ã確èªããŠè§£æ±ºããŸããã ããã¯ACTIVEããªããŒã¿ãŒã§ãªããžã§ã¯ããè¿ããŸãã ããªããŒã¿ãŒãèšå®ãããŠããŠãããªããŒã¿ãŒãçã§ââããããã®æ¡ä»¶ãæºããããŠããå Žåã
ç§ã®äŸã§ã¯ããã¹ããããã³ã³ããŒãã³ãã§äœ¿çšããããªã¢ã¯ãã£ããã©ãŒã ã§ãããããŸãã
return this.formBuilder.group({
username: ['', [Validators.required, Validators.min(3), Validators.email]],
...
});
ååã¯ãã¹ãã®ã¿ãç®çãšããŠããŸã
<app-input name="txtfield"
[parentForm]="loginForm" parentFormControlName="txtfield"
></app-input>
<div [formGroup]="parentForm" class="form-control-group">
...
<input #inputField name="{{parentFormControlName}}"
formControlName="{{parentFormControlName}}"
matInput
placeholder="{{placeholderTxt}}"
>
...
</div>
ãã¹ããããã³ã³ããŒãã³ãã§ã¯ããå¿ é ãã®ããªããŒã¿ãŒã®ã¿ãå¿ èŠãªãããAfterViewIinitã®åŸã«äžåºŠã ããã§ãã¯ããŸãã
ngAfterViewInit() {
// Lookup if this field is required or not
if (this.parentForm.controls[this.parentFormControlName].validator != null) {
// MAYBE CHECK FOR required field in returned OBJECT!!
console.log('Validators of ' + this.parentFormControlName + ' = ',
JSON.stringify(
this.parentForm.controls[this.parentFormControlName]
.validator(this.parentForm.controls['username']);)
);
} else {
console.log('No validator set for component ' + this.parentFormControlName);
}
ãããã¬ãŒãåæ¢ããŠããéã®ãã©ãŠã¶ãŒã³ã³ãœãŒã«ã§ã®åºåïŒ
[DEBUG] STATUS of username = {"required":true}
>this.parentForm.controls[this.parentFormControlName].validator(this.parentForm.controls[this.parentFormControlName])
{required: true}
required: true
__proto__: Object
ãã以å€ã®å Žå-ããªããŒã¿ãŒãèšå®ãããŠããªãå Žå-ãnullããšè¡šç€ºãããŸãïŒ
input-text-fieldã«ããã©ã«ãå€ãããå Žåãããã¯å¿ é å€ãtrueã§ããããšã瀺ããŸãããããã£ãŒã«ããå¿ é ã§ãããå ¥åãããŠããªãå Žåã«ã®ã¿ããã£ãŒã«ãïŒ=倪åã®è¡ïŒã匷調衚瀺ããŸãã
ãDoCheckããŸãã¯ãOnChangesãã䜿çšããŠå€æŽãç£èŠããå¿ èŠã«å¿ããŠãemailããŸãã¯ãminãããªããŒã¿ãŒãååŸããå Žåã¯ãä»ã®ããªããŒã¿ãŒã¹ããŒã¿ã¹ããã€ã§ã確èªã§ããŸãã
@AngularããŒã ãçŸåšã®ããªããŒã¿ãŒãªã¹ãããã§ãã¯ããå®è¡æã«ç¹å®ã®ããªããŒã¿ãŒãåé€ããAPIãæ¬åœã«å¿ èŠã§ãã ããã¯å€ãã®åé¡ã解決ããŸãã
ãªããcontrol.errorsããšãcontrols.validatorsããpreatymutchãåãããšãããŠããã®ã§ããïŒ
ã .errors ãã¯ããšã©ãŒç¶æ
ã«éããããããã¹ãŠã®ãšã©ãŒã衚瀺ããå¿
èŠããããŸãã
ã .validators ãã¯ããã®ã³ã³ãããŒã«ã®ããã«ãç»é²ãããŠãããã¹ãŠã®ããªããŒã¿ãŒãè¿ãå¿
èŠããããŸãã
ãããšåããããç°¡åã§ããïŒ
ãã®æ©èœãèŠããã§ãã ãããïŒ ç§ãèŠãŠãã倧ããªåé¡ã®1ã€ã¯ãããªããŒã¿ãŒãïŒéåžžã¯ïŒçŽç²é¢æ°ã§ãããšããããšã§ããã€ãŸããããªããŒã¿ãŒã¯æ·±ããã¹ãããããšãã§ããŸãã
ç§ãã¡ã®ãããžã§ã¯ãã«ã¯ãä»ã®ããªããŒã¿ãŒïŒãªã©ïŒããæ§ç¯ããããã¡ã€ã³é¢é£ã®ããªããŒã¿ãŒããããããããŸãã ããšãã°ãç§ãã¡ã®IBANããªããŒã¿ãŒã¯ã exactLength
ã pattern
ãããã³å
éšã§IBANãã§ãã¯ãã£ãžããããªããŒã¿ãŒã䜿çšããŸãã ãã®ãã¿ãŒã³ã«åŸããšãããå
·äœçãªæ€èšŒãšã©ãŒãçºçããåé¡ããã詳现ã«èª¬æãããšã©ãŒã¡ãã»ãŒãžã䜿çšã§ããããã«ãªããŸãïŒãŠãŒã¶ããªãã£ã«ãšã£ãŠã¯ããè¯ãïŒã
ãããã£ãŠããã¹ãŠã®ããªããŒã¿ãŒãååŸããããã®æ°ããæ¹æ³ãæ€èšããå Žåã質åã¯æ¬¡ã®ãšããã§ãããäžäœã®ããªããŒã¿ãŒãã®ã¿ãè¿ãããŸããïŒ ããã«ããããã®ããªããŒã¿ãŒã®ååã¯äœã§ããïŒ å šäœãšããŠãçŸåšã®æ€èšŒã®å®è£ ã§ã¯ãç°¡åãªè§£æ±ºçã¯ãªãããã«æãããŸã...
TL; DRïŒAngularãã©ãŒã ã¢ãžã¥ãŒã«ã®å€ãã®ãã®ãå€æŽããæ¢åã®ã³ãŒããå£ããã«ããã¯äžå¯èœã§ãã
çãããé¢é£ãããœãŒã¹ã³ãŒãã¯æ¬¡ã®ãšããã§ãã
packages / forms / src / model.ts
packages / forms / src / validators.ts
ãããŠå€åpackages / forms / src / directives / validators.ts
次ã®åé¡ãèŠã€ãããŸããã
addValidator
é¢æ°ãå®è£
ããããšã¯ã§ããŸããã removeValidator
é¢æ°ãå®è£
ããããšã¯ã§ããŸãããsetValidators
ãå®è¡ãããšãcomposeé¢æ°ãæçµçã«åŒã³åºãããŸãã ãã¹ãŠã®ããªããŒã¿ãŒé¢æ°ã1ã€ã®é¢æ°ã«ãŸãšããå
éšã®_executeValidatorsé¢æ°ãåŒã³åºããŠå®éã«åŒã³åºããŸãã ãããã£ãŠãæçµçã«ã¯å
ã®ããªããŒã¿ãŒã®é
åããªãããã¹ãŠã®ãšã©ãŒã®ãªã¹ããããŒãžããã巚倧ãªã¡ã¬ããªããŒã¿ãŒãããããŸããããã®ããšãããããªããŒã¿ãŒã®æŠå¿µã«ããã€ãã®é倧ãªå€æŽãå°å
¥ããã«getValidators
ãŸãã¯removeValidator
ãå®è£
ããããšã¯äžå¯èœã§ãããšçµè«ä»ããŸããã addValidators
ãå®è£
ããããšã¯å¯èœã®ããã§ãããããªããŒã¿ãŒãè¿œå ããããšããã§ãããæ¢åã®ããªããŒã¿ãŒãåé€ã§ããªãå Žåã誰ããããå¿
èŠãšããŸããïŒ
ã§ã¯ãã¢ããªã«æ¡ä»¶ä»ãã®åçæ€èšŒãå®è£ ããå Žåãããšãã°ãæ¢åã®ãã¹ãŠã®ã¡ãŒã«ããªããŒã¿ãŒã倱ãããšãªããã®ãã§ãã¯ããã¯ã¹ãèšå®ãããŠããå Žåã«ãã®ã¡ãŒã«ãã£ãŒã«ããå¿ é ã«ããå Žåã¯ãã©ãããã°ããã§ããããã ç§ã¯2ã€ã®ã¢ãããŒããèŠã€ããŸããïŒ
setValidator
é¢æ°ã䜿çšããŠãValidator.required +ãã¹ãŠã®ããã©ã«ãã®ããªããŒã¿ãŒãæž¡ããŸãã@ ganqqwerty âŠæ£è§£ã§ãã ãããã addValidator(...)
ãŸãã¯removeValidator(...)
ãååšããªãçç±ã§ãã èå¥ã¯ãããŸããã ããªããŒã¿ãŒèªäœã¯ãã©ã®ã³ã³ãããŒã«ãå®è¡ãããŠããããç¥ããŸããã
@ganqqwertyãããå®è£ ããã®ãç°¡åã ãšèšã£ãŠããããã§ã¯ãããŸããããããã§ã¯ããªãã®æšè«ãæå¹ã§ã¯ãªããšæããŸãã
æ£èŠè¡šçŸããªããŒã¿ãŒãã©ã®ããã«åé€ã§ããŸãã
ããªããŒã¿ãŒãžã®åç §ãæž¡ãããšã«ãã£ãŠã ã€ãã³ããªã¹ããŒãåé€ããã®ãšåãæ¹æ³ã§ãã
ãããã£ãŠãæçµçã«ã¯å ã®ããªããŒã¿ãŒã®é åããããŸãã
ããã¯åãªãå éšèšèšã®æ±ºå®ã§ãããçŸåšããããªãã¯APIã®ã©ãã«ãå ¬éãããŠããŸããã é¢æ°ãäœåºŠãäœæããã®ã§ã¯ãªããå ã®é åãä¿æããããšãéžæãããšãããªããŒã¿ãŒã®é åãã¯ããŒãžã£ãŒã«ä¿æããå¿ èŠãããè¿œå ã®é¢æ°ããªããããå®éã«ã¯ããã©ãŒãã³ã¹äžã®å©ç¹ããããŸãã
æ¢åã®ãã¹ãŠã®é»åã¡ãŒã«ããªããŒã¿ãŒã倱ãããšãªããã®ãã§ãã¯ããã¯ã¹ãèšå®ãããŠããå Žåã«ãã®é»åã¡ãŒã«ãã£ãŒã«ããå¿ é ã«ããã«ã¯ïŒ[...]ãã©ãŒã å¶åŸ¡å¿ é ããªããŒã¿ãŒã䜿çšãã代ããã«ããã§ãã¯ããã¯ã¹ãšãã£ãŒã«ãã®å€æŽã®äž¡æ¹ãç£èŠãããã©ãŒã ã°ã«ãŒãããªããŒã¿ãŒãäœæã§ããŸãã
ããã¯æå³ãããåäœã§ã¯ãããŸãããïŒ é»åã¡ãŒã«ãã£ãŒã«ãã䜿çšãããã©ãŒã ã³ã³ãããŒã«ã¯ãæå¹ãªé»åã¡ãŒã«ã¢ãã¬ã¹ãããã°ããèªäœã§æå¹ã§ãã ãã§ãã¯ããã¯ã¹ã®å€ãtrue
ã®å Žåãé»åã¡ãŒã«ãååšããå Žåã_group_ã¯æå¹ã§ãã ããã¯ããªããŒã¿ãŒã®åé¿çã§ã¯ãããŸãããããã©ãŒã ã®æ£ããã¬ãã«ã§ã®é©åãªäœ¿çšæ³ã§ãã
ãããæ確ã«ããŠãããŠããããšãïŒ ãã®ãããªæ©èœã®å®è£ ãã¹ã±ãžã¥ãŒã«ã§ãããšããããšã§ããïŒ
ããªããŒã¿ãŒãžã®åç §ãæž¡ãããšã«ãã£ãŠã
ãããã£ãŠãããªããŒã¿ãŒãžã®åç
§ãä¿æãããšããããåé€ããããšãå¯èœã«ãªããŸãã ããªããŒã¿ãŒãšããŠç¡åé¢æ°ãæäŸããã ãã§ã¯ããããåé€ããããšã¯ã§ããŸããã ããŒãã確ãã«ããã¯removeEventListener
ã®ããã«èŠããŸã
ãã®æ©èœããªããšãç¹å®ã®ã³ã³ãããŒã«ããç¹å®ã®ããªããŒã¿ãŒãåé€ããããšã¯ã§ããŸããã
ããã¯ç§ãä»å¿ èŠãšããŠãããã®ã§ãããç§ã¯ããã解決ããããšã¯ã§ããŸããã éåžžã«åºæ¬çãªãã®ãAngularã§ã¯äžå¯èœãªå ŽåããããŸãã
this.myAbstractFormControl.removeValidatorAndKeepTheRestAsIs(Validators.required)
@andreElricoããªããŒã¿ãŒãåé€ããããã®ãŠãŒã¹ã±ãŒã¹ã¯äœã§ããïŒ ããã«ã€ããŠèããã°èããã»ã©ããã©ãŒã ã®ããªããŒã¿ãŒãå€æŽããããšã®æå³ããããã«ãããªããŸãã ãã©ãŒã ã®å¥ã®ãã£ãŒã«ãã«åºã¥ããŠããªããŒã¿ãŒãåçã«å€æŽããå¿ èŠãããå ŽåãããªããŒã¿ãŒã®é 眮ã¯ééã£ãŠããŸããå¿ èŠãªã®ã¯ããã©ãŒã ã³ã³ãããŒã«ããªããŒã¿ãŒã§ã¯ãªãããã©ãŒã ã°ã«ãŒãããªããŒã¿ãŒã§ãã
ããšãã°ã2ã€ã®ã·ããªãªã§åçã«å ¥åãä»ããŠæäŸãããã®ãšåãformGroupã䜿çšããããšããŠããŸãã 1ã€ã¯åãã£ãŒã«ãã§å¿ èŠãªãã®ã§ããã2ã€ç®ã¯å¿ èŠãªIFãååšãããã®ãåé€ããatLeastOneFieldããªããŒã¿ãŒãformGroupã«é©çšããå Žåã§ãã
ãããç§ã®stackblitzImãåãçµãã§ãããšããã§ãã
æ¢åã®æ€èšŒåŠçã«é¢ããŠAngularããŒã ãçã¿åºããèšèšäžã®æ¬ é¥ãä¿è·ãããã®ãããçç±ãããããŸããã
AngularForm-æ€èšŒã¯CRUDã§ããå¿
èŠããããŸãã
@andreElricoç§ãèšã£ãããã«ããã©ãŒã ã«çžäºã«äŸåããæ€èšŒãæã€2ã€ã®å ¥åãããå ŽåãããªããŒã¿ãŒã¯ãã©ãŒã ã³ã³ãããŒã«ã§ã¯ãªããã©ãŒã ã°ã«ãŒãã«ããå¿ èŠããããŸãã
ããšãã°ã2ã€ã®ãã¹ã¯ãŒããã£ãŒã«ããããå Žåãæåã®ã³ã³ãããŒã«ãå€æŽããããã³ã«2çªç®ã®ã³ã³ãããŒã«ã®ããªããŒã¿ãŒãå€æŽããªãã§ãã ããã 代ããã«ãããªããŒã¿ãŒã¯2ã€ã®ãã¹ã¯ãŒããã£ãŒã«ããå«ãã°ã«ãŒãã«ç§»åããå¿ èŠããããŸãã åãã¹ã¯ãŒããã£ãŒã«ãã«ã¯ããã¹ã¯ãŒãã8æå以äžã§ããå¿ èŠããããšããæ€èšŒããããŸãããã°ã«ãŒãã«ã¯ãåãã§ããå¿ èŠããããšããããªããŒã¿ãŒããããŸãã ããèªäœã§ã¯ãåãã¹ã¯ãŒããã£ãŒã«ãã¯ä»ã®ãã¹ã¯ãŒããã£ãŒã«ãã®ååšãèªèããŠããŸããã ã°ã«ãŒãã¯ããããäžç·ã«ä¿æããŸãã
ããªããã®ãããªãã®ãæã£ãŠãããªã
( ) a
( ) b
( ) other [ _____ ]
ããã§ããŠãŒã¶ãŒãããã®ä»ããéžæããå Žåããã®æšªã«å ¥åãã£ãŒã«ããå¿ èŠã§ãããã®å Žåããå ¥åãã£ãŒã«ãã§ãå¿ é ãã®ããªããŒã¿ãŒãåãæ¿ããªãã§ãã ããã 代ããã«ããã©ãŒã ã°ã«ãŒãå šäœãæ€èšŒããå¿ èŠããããŸããã©ãžãªãã¿ã³ã³ã³ãããŒã«ã¯ãaãããbãããŸãã¯ãotherãã®ããããã§ããå¿ èŠãããããotherãã®å Žåã¯å ¥åãã£ãŒã«ããååšããå¿ èŠããããŸãã
ã©ãžãªãã¿ã³ã«ãªã¹ããŒãé 眮ããŠãããã©ãžãªãã¿ã³ã®å€ã«åºã¥ããŠå ¥åãã£ãŒã«ãã®ãå¿ é ãããªããŒã¿ãŒãåãæ¿ããå¿ èŠã¯ãããŸããã
æ€èšŒã«CRUDAPIãå¿ èŠã ãšããªããä¿¡ããŠããçç±ãããããŸããã ç§ã¯äœãæè·ããŠããŸãããç§ã¯åççã§è°è«ãæã£ãŠè©±ããŠããã®ã§ãã ããªããŒã¿ãŒãååŸãåé€ãåãæ¿ãããããã®ã¡ãœãããå®è£ ãã¹ãã§ã¯ãªããšèšã£ãŠããã®ã§ã¯ãããŸãããããã«ããã»ãšãã©ã®äººããå®éã«ã¯ã¢ã³ããã¿ãŒã³ã§ããCRUDæ€èšŒã®ãŠãŒã¹ã±ãŒã¹ãæã£ãŠãããšèšã£ãŠããŸãã ã³ã³ãããŒã«ã¯ã¹ã¿ã³ãã¢ãã³ãŠãããã§ãããåç¶æéäžã¯æ€èšŒã«ãŒã«ãå€æŽããŸããã ã³ã³ãããŒã«ãäŸåããŠããå Žåããããã¯ã°ã«ãŒãã«å ¥ããããã°ã«ãŒããæ€èšŒãããŸãã
ã³ã¡ã³ããšæéãããããšã@lazarljubenovic ã
ããªãã¯ç§ã®stackblitzãããèŠãŠããªãããã«æããŸãã 1ã€ã®ã·ããªãªã®formGroupã«ãã©ããã³ã°ãããžãã¯ãé©çšããŠããŸãã ãã©ãŒã ã«ã¯ãããªããŒã¿ãŒãåçã«å€æŽããå¿
èŠããã2ã€ã®ç°ãªãã·ããªãªããããŸãã ãããŠãformGroupãæ±ããã®ã段éãã§ã¯ãããªããŒã¿ãŒã¯ãã§ã«ãæ§æããããŠããã®ã§ãCRUDã¯ãããŸããïŒDã
ç§ã¯ãã®åé¡ãåé¿ããããšãã§ããããããã€ãä¿®æ£ãããããšãé¡ã£ãŠããŸãã
167ðã¯ãã®æ©èœã«å¯Ÿããé«ãèŠæãåæ ããŠããããã§ãã
æéãããã°ããã£ãšç¥ãããã§ãã
ãã³ã³ãããŒã«ã¯ã¹ã¿ã³ãã¢ãã³ãŠãããã§ãããåç¶æéäžã¯æ€èšŒã«ãŒã«ãå€æŽããŸãããã
ããã«é¢ãããªãœãŒã¹ã¯ãããŸããïŒ
ãã³ã³ãããŒã«ãäŸåããŠããå Žåããããã¯ã°ã«ãŒãã«å ¥ããããã°ã«ãŒããæ€èšŒãããŸããã
ããã¯ãå®éã«ã¯éçããããŸãã
ãŸãããã®åé¡ãšã¯é¢ä¿ãããŸããã
ã°ã«ãŒããã³ã³ãããŒã«ã®æ€èšŒãåŒãç¶ãå Žåããšã©ãŒã¯ã°ã«ãŒãã«èšå®ããããããã³ã³ãããŒã«ã«èŠèŠçã«åæ ãããŸããã ãããã£ãŠãåã³ã³ãããŒã«ã«å¯ŸããŠæåã§ãšã©ãŒãèšå®ããã³åé€ããå¿
èŠããããŸãã ïŒããã¯*ã®å€§ããªèŠçã§ãïŒã
è¯ãé±æ«ããéãããã ããã
ç§ã¯ç¢ºãã«@lazarljubenovicã®èŠæ¹ãç解ããŠããŸãã
ãã ããç§ã¯ãè€éãªæ§æãå¿ èŠãšããéåžžã«åçãªãã«ãããŒãã®ãšã³ã¿ãŒãã©ã€ãºãã©ãŒã ã«åãçµãã§ããŸã...å€ãã®é衚瀺/衚瀺ãæ€èšŒèŠä»¶ã®äŸåé¢ä¿ãã§ãŒã³ãªã©ã
ãã®è€éããåŠçããæ¹æ³ã¯ãäŸåé¢ä¿ã®ããªã¬ãŒãæ åœãããã©ãŒã ã³ã³ãããŒã«ãã°ã«ãŒãããŸãã¯é åã§valueChangesããµãã¹ã¯ã©ã€ãããã·ããªãªããšã«setValidatorsãŸãã¯clearValidatorsã䜿çšããããšã§ãã ç¹å®ã®ããªããŒã¿ãŒãã¿ãŒã²ããã«ããæ¹æ³ããªãããããã€ã§ãé©çšãããå¯èœæ§ã®ããæ€èšŒã«ãŒã«ã®åã»ãããä¿åããããããåé©çšããŸãã ãã¹ãŠã®ããªããŒã¿ãŒãååŸããããåã ã®ããªããŒã¿ãŒãè¿œå ããããç¹å®ã®ããªããŒã¿ãŒãåé€ã®å¯Ÿè±¡ã«ãããã§ãããšäŸ¿å©ã§ããããã¯ããã¹ãŠäžå€æ§ã念é ã«çœ®ããŠèšèšã§ããããã§ãã
ãã³ã³ãããŒã«ã¯ã¹ã¿ã³ãã¢ãã³ãŠãããã§ãããåç¶æéäžã¯æ€èšŒã«ãŒã«ãå€æŽããŸãããã
ããã«é¢ãããªãœãŒã¹ã¯ãããŸããïŒ
ããã; ããã¯æ¬åœã«ãã©ãŒã ã®ãã¶ã€ã³ã®ç§ã®è§£éã§ãã
ã°ã«ãŒããã³ã³ãããŒã«ã®æ€èšŒãåŒãç¶ãå Žåããšã©ãŒã¯ã°ã«ãŒãã«èšå®ããããããã³ã³ãããŒã«ã«èŠèŠçã«åæ ãããŸããã
æ£çŽãªãšããããããã®ãšã©ãŒãçºçããã¯ãã®UIã®èŠ³ç¹ãããçãããã§ãã 2ã€ã®ãã£ãŒã«ããäžç·ã«åçãããªããããã©ãŒã ã倧ããé¢ããŠããå Žåããšã©ãŒãã©ãã«æžã蟌ãå¿ èŠããããŸããïŒ æåã«äžæ©äžãã£ãŠãã©ãŒã ã®UXãä¿®æ£ããå¿ èŠãããããã«ç§ã«ã¯æããŸãã
ãã¡ããããã©ãŒã ã¯éç£ã§ããããã¹ãŠã®ãŠãŒã¹ã±ãŒã¹ã«é©åããããã§ã¯ãããŸããã _æ¬åœã«_ã¯ã¬ã€ãžãŒãªã³ã³ãããŒã«ãåããéåžžã«è€éãªãã©ãŒã ãããå Žåã @angular/forms
ã¯ãŸã£ãã䜿çšããŸããã @angular/forms
ã¯ããŠãŒã¹ã±ãŒã¹ã®95ïŒ
ãã«ããŒããå€ãã®åŽåããããã«ãã©ãŒã ããã°ããäœæã§ããåªãããŠãŒãã£ãªãã£ã ãšæããŸãã
Array#map
ã Array#filter
ã Array#reduce
ã䜿çšããã®ã奜ããªã®ãšåãããã«ãã€ã³ããã¯ã¹å€æ°ã䜿çšããå€ãè¯ãfor
ã«ãŒãããããè€éãªå埩ã®æè¯ã®ãœãªã¥ãŒã·ã§ã³ã§ããå ŽåããããŸãã ã
ãããã®ã¡ãœãããè¿œå ããã®ã§ã¯ãªãããšãããäžåºŠæ確ã«ããŠãããããšæããŸãã _倧å€æ°ã®äººãããããæªçšãããããªæ°ãããŸãã å€åããã¯ãããã¬ã³ã§ãããã ç¹°ãè¿ãã«ãªããŸããã誰ããããã誀çšããå¯èœæ§ããããšããçç±ã ãã§ãæçšãªãã®ããã¬ãŒã ã¯ãŒã¯ã«è¿œå ãã¹ãã§ã¯ãªããšæããŸãã ãã€ã¬ã®æ°Žã§æ¯ã磚ãããšãã§ããŸãããã®ããããã€ã¬ã¯çŠæ¢ãããŠããŸããã
éåžžã«è€éãªãã©ãŒã ã§éåžžã«ã¯ã¬ã€ãžãŒãªã³ã³ãããŒã«ã䜿çšããŠããå Žåã¯ã@ angle / formsããŸã£ãã䜿çšããŸããã @ angle / formsã¯ããŠãŒã¹ã±ãŒã¹ã®95ïŒ ãã«ããŒããå€ãã®åŽåããããã«ãã©ãŒã ããã°ããäœæã§ããåªãããŠãŒãã£ãªãã£ã ãšæããŸãã
ããã¯AngularFormsã®å ¬åŒã®åžå Žããžã·ã§ãã³ã°ã§ããïŒ å·šå€§ãªãããžã§ã¯ãã«åœ¹ç«ã€äžèœããŒã«ãšããŠèããŸããã
éåžžã«è€éãªãã©ãŒã ã§éåžžã«ã¯ã¬ã€ãžãŒãªã³ã³ãããŒã«ã䜿çšããŠããå Žåã¯ã@ angle / formsããŸã£ãã䜿çšããŸããã @ angle / formsã¯ããŠãŒã¹ã±ãŒã¹ã®95ïŒ ãã«ããŒããå€ãã®åŽåããããã«ãã©ãŒã ããã°ããäœæã§ããåªãããŠãŒãã£ãªãã£ã ãšæããŸãã
ããã¯AngularFormsã®å ¬åŒã®åžå Žããžã·ã§ãã³ã°ã§ããïŒ å·šå€§ãªãããžã§ã¯ãã«åœ¹ç«ã€äžèœããŒã«ãšããŠèããŸããã
ããªã¢ã¯ãã£ããã©ãŒã ãã¯ãæ€èšŒãå®å šã«å¶åŸ¡ã§ãããªã©ãè€éã§é«åºŠã«ã«ã¹ã¿ãã€ãºããããŠãŒã¹ã±ãŒã¹ã察象ãšããŠããŸã;ïŒ
ããªãã¯ãããå®å šã«å¶åŸ¡ããããšãã§ããŸãã æ€èšŒãã察象ïŒã°ã«ãŒããŸãã¯ã³ã³ãããŒã«ïŒãé©åã«å€å¥ããå¿ èŠããããŸãã
ããã¯äœãçœåŒåã«ãªããŸãããïŒ ãã¹ãŠãåãé¢ããŠããããã«ãå ¥åãšããŠformGroupã®ã¿ã䜿çšããŠããªããŒã¿ãŒãåçã«å€æŽããããšæããŸã!!! ãªã¢ã¯ãã£ããã©ãŒã ã¯çŽ æŽãããã§ãããããã¯ç§ã®å¯äžã®æã¡ãããã§ãã
SoooooooooããªããŒã¿ãŒãåçã«è¿œå ããã³ãŒãããŠããããã¹ãããã«ã¯ã©ãããã°ããã§ããïŒ
ããªããŒã¿ãŒãé©çšããã³ã³ãããŒã«ã_èªã¿åã_ããšãã§ããªããããæãããªåäœãã¹ãã¯æ©èœããªãããã§ãã
_ããã¯æ©èœããŸãã_
expect(component.formControl.validators.length).toEqual(2);
æŽæ°ïŒ
å®éãããªãã¯ããããã®ããã«è¡ãããšãã§ããŸãã ãã ããããªããŒã¿ãŒãèªã¿åãæ¹ãæããã«å®äŸ¡ã§ãã
component.myCtrl.setValue('');
expect(component.myCtrl.errors.required).toBeTrue();
ç§ã¯ãªã¢ã¯ãã£ããã©ãŒã ã®å€§ãã¡ã³ã§ããããããã䜿ã£ãŠäœãã§ãããã倧奜ãã§ãããFormControlã«ããªããŒã¿ãŒã«ã€ããŠå°ããããšãã§ããªããªã©ã®å°ããªããšã¯èŠèœãšãã®ããã§ãã FormControlã«ã¯éåžžã«å€ãã®ç¶æ
ããããã£ããããšãããšãå°ãªããšã.required
ããããã£ã䜿çšå¯èœã«ããããšã劚ãããã®ã¯äœã§ããïŒ ãããæ¥åžžç掻ã«åœãŠã¯ãŸããšæ³åããŠã¿ãŠãã ãã...
ç§ïŒããã«ã¡ã¯ãç§ã¯ç§ã®çŽæã®ããã«ããã«ããŸãã
åä»ïŒç³ãèš³ãããŸãããããäŒãã§ããŸããã
ç§ïŒã©ãããŠïŒ ä»ãçŽæããããŸãã
åä»ä¿ïŒç§ã¯ç¥ããªãè©ãããããã
å°ãäžè¬åããŠããŸãããFormControlããããã£å€ãæž¡ãã°ããããã®å€ã«ãã¢ã¯ã»ã¹ã§ããã¯ãã§ãã
å°ãªããšã.requiredããããã£ãå©çšå¯èœã«ããããšã劚ãããã®
ç¬èªã®required
ããªããŒã¿ãŒãäœæã§ãããšããäºå®ã Angularã¯ããªãã®é¢æ°ãäœãããã®ããç¥ãããšãã§ããŸããã
100ïŒ
ã¯ãããç解ããŠããŸããç§ã¯ãããé¢æ°ã«åºã¥ããŠãããšèšã£ãŠããã®ã§ã¯ãããŸããã ãã£ãŒã«ããå¿
é ã§ããããšãç¥ãããšã¯ãæ§æå¯èœã§ã¢ã¯ã»ã¹å¯èœã§ãããUIã«åæ ãããæå¹å/ç¡å¹åãç¥ãããšãšåããããåºæ¬çã§ãã
éçºè
ãFormControlãæäœããã ãã§ãå¿
èŠãªããŒã«ãŒãæ¡ä»¶ä»ãã§è¡šç€ºãããªã©ã®ããšãã§ããããã«ãå¿
èŠãªãã£ãŒã«ãã«å¯ŸããŠåæ§ã®æ©èœãååŸã§ããããã«ããããã«ã§ããããšã¯ãããŸããïŒ
ããã«ã¡ã¯ãããã¯ç§ãã¡ã®ææ°ã®ããã¯ã§ãããå¿ èŠãªå ¥åãèªåçã«ããŒã¯ããŸãïŒ httpsïŒ//stackblitz.com/edit/material-input-auto-required-asteriskã åãæŠå¿µãmat-selectããã®ä»ã®ã©ã€ãã©ãªã«ãé©çšã§ããŸãã
const _clearValidators = AbstractControl.prototype.clearValidators;
AbstractControl.prototype.clearValidators = function(){
(this as any).isRequired = false;
_clearValidators.call(this);
}
const _setValidators = AbstractControl.prototype.setValidators;
AbstractControl.prototype.setValidators = function(newValidator: ValidatorFn | ValidatorFn[] | null): void {
(this as any).isRequired = false;
_setValidators.call(this, newValidator);
}
export function isRequired(control: AbstractControl): ValidationErrors | null{
(control as any).isRequired = true;
return Validators.required(control);
}
@Directive({ selector: '[matInput]:not([required])' })
export class MatInputRequiredDirective implements DoCheck {
constructor(private readonly input: MatInput) { }
ngDoCheck() {
const isRequired = (this.input.ngControl && this.input.ngControl.control as any).isRequired || false;
if(isRequired !== this.input.required){
this.input.required = isRequired;
this.input.ngOnChanges();
}
}
}
100ïŒ ã¯ãããç解ããŠããŸããç§ã¯ãããé¢æ°ã«åºã¥ããŠãããšèšã£ãŠããã®ã§ã¯ãããŸããã ãã£ãŒã«ããå¿ é ã§ããããšãç¥ãããšã¯ãæ§æå¯èœã§ã¢ã¯ã»ã¹å¯èœã§ãããUIã«åæ ãããæå¹å/ç¡å¹åãç¥ãããšãšåããããåºæ¬çã§ãã
ç§ã¯ã¡ãã£ãšç¢ºä¿¡ãæãŠãŸããã ãèŠä»¶ãã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«éåžžã«åºæã§ãã 空ã®æååã¯ãå¿ é ãæ¡ä»¶ãééããŸããïŒ ãŒãã¯ã©ãã§ããïŒ è€æ°éžæã®ç©ºã®é åïŒ ãã§ãã¯ããã¯ã¹ãééã£ãŠããŸããïŒ ãã«ãæªå®çŸ©ïŒ
éçºè ãFormControlãæäœããã ãã§ãå¿ èŠãªããŒã«ãŒãæ¡ä»¶ä»ãã§è¡šç€ºãããªã©ã®ããšãã§ããããã«ãå¿ èŠãªãã£ãŒã«ãã«å¯ŸããŠåæ§ã®æ©èœãååŸã§ããããã«ããããã«ã§ããããšã¯ãããŸããïŒ
å¿ èŠãªæ¡ä»¶ã«åºã¥ããŠããã§ã«æ¡ä»¶ä»ãã§ãšã©ãŒã衚瀺/é衚瀺ã«ããããšãã§ããŸãã ãšã©ãŒãååšãããããšãã£ãŠãå¿ ãããã©ããã«è¡šç€ºããå¿ èŠããããšã¯éããŸããã ããã§ã¯ãåã«ãšã©ãŒïŒå©çšå¯èœïŒãç §äŒããã®ã§ã¯ãªããããªããŒã¿ãŒãç §äŒããããšãã©ã®ããã«åœ¹ç«ã€ãããããŸããã
ç§ã¯ã¡ãã£ãšç¢ºä¿¡ãæãŠãŸããã ãèŠä»¶ãã¯ãã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«éåžžã«åºæã§ãã 空ã®æååã¯ãå¿ é ãæ¡ä»¶ãééããŸããïŒ ãŒãã¯ã©ãã§ããïŒ è€æ°éžæã®ç©ºã®é åïŒ ãã§ãã¯ããã¯ã¹ãééã£ãŠããŸããïŒ ãã«ãæªå®çŸ©ïŒ
æå¹/ç¡å¹ã«ãªã£ãŠãããã£ãŒã«ããã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«éåžžã«åºæã§ãããšäž»åŒµã§ããŸãããFormControlã¯ãéçºè ãã³ã³ã¹ãã©ã¯ã¿ãŒãšã¢ã¯ã»ãµãŒãä»ããŠããã管çããæ©èœãæäŸããŸãã å¿ èŠãšãããã®ã¯ææ§ãªç·ã§ãããç§ã¯ããªããã©ãããæ¥ãŠããã®ããç解ããŸãã ããã¯å人çãªå¥œã¿ãããããŸããããå€ã®æå¹æ§ã瀺ãã®ãšåããããã衚瀺ç¶æ ïŒæå¹/ç¡å¹ãæå¹/ç¡å¹ãªã©ïŒã§ãã
å¿ èŠãªæ¡ä»¶ã«åºã¥ããŠããã§ã«æ¡ä»¶ä»ãã§ãšã©ãŒã衚瀺/é衚瀺ã«ããããšãã§ããŸãã ãšã©ãŒãååšãããããšãã£ãŠãå¿ ãããã©ããã«è¡šç€ºããå¿ èŠããããšã¯éããŸããã ããã§ã¯ãåã«ãšã©ãŒïŒå©çšå¯èœïŒãç §äŒããã®ã§ã¯ãªããããªããŒã¿ãŒãç §äŒããããšãã©ã®ããã«åœ¹ç«ã€ãããããŸããã
ã¯ããæ¡ä»¶ä»ãã§ãšã©ãŒãé衚瀺/衚瀺ã§ããŸããããããã®ãšã©ãŒã解決ããããšãæåŸ
ãããç¶æ
ã«äŸåããªããã¬ãŒã³ããŒã·ã§ã³éšåã¯äœ¿çšã§ããªããªããŸãã ããªããŒã¿ãŒã«åºã¥ããŠã¢ã¹ã¿ãªã¹ã¯ã衚瀺ããããšã¯ã§ããŸããããããã®ããªããŒã¿ãŒãæºãããããšããããã¯äœ¿çšã§ããªããªãããã§ãã
ä»ã®ãšãããç§ã¯ãããåé¿ããå¿
èŠããããšæããŸãã
æå¹/ç¡å¹ã«ãªã£ãŠãããã£ãŒã«ãããã¢ããªã±ãŒã·ã§ã³ã®ããžãã¹ããžãã¯ã«éåžžã«åºæã§ãã
æ¹æ³ãããããŸããã
ããªããŒã¿ãŒã«åºã¥ãã¢ã¹ã¿ãªã¹ã¯ã衚瀺ã§ããŸãã
ãããã£ãŠã代ããã«ãç¬èªã®ãå¿ é ãã»ãã³ãã£ã¯ã¹ã«åºã¥ããŠããªããŒã¿ãŒãè¿œå ããŸãã ãã¹ãŠãã¯ã³ã©ã€ããŒã«ãªãããã§ã¯ãããŸããã
ç§ã¯ã·ããªãªããµããŒãããããã®åççãªæ¹æ³ãæ¢ããŠããŸãããå¿ ãããã¯ã³ã©ã€ããŒã§ã¯ãããŸããã ç§ã¯ãŸããç§ã®ãã®ããããŠããå Žåã«åããŠãããªãã®èŠç¹ãç解ããããšããŠããŸãã
ç§ã®ã»ãã³ãã£ã¯ã¹ãåãªãããã©ã§ãããValidators.requiredæ€èšŒã掻çšããããã ãã«å¿
èŠãªå Žåã¯ã©ããªããŸããïŒ ä»¥äžã®StackBlitzã®äŸã§ã¯ãããã¹ããã£ãŒã«ãã«è¿œå ããŠå€ãå
¥åããå Žåããããç¥ãå¯äžã®æ¹æ³ã¯ã field.errors
ãªããžã§ã¯ããä»ããŠãããªããŒã¿ãŒã«é¢é£ä»ããããããããã£ãæ¢ãããšã§ãã ãã ããValidatorãæºãããããšããã®ããããã£ã¯ååšããªããªããŸãã ãã¶ãç§ã®ã¢ãããŒãã¯ééã£ãŠããŸãããFormControlã掻çšããŠãç§ãå©çšããŠããªããããéæããããã®ããè¯ãæ¹æ³ã¯ãããŸããïŒ
å¥ã®ãã£ãŒã«ãã®æå¹æ§ã«åºã¥ããŠããªããŒã¿ãŒãåãæ¿ããããšã¯æ³å®ãããŠããŸããã ã°ã«ãŒãããªããŒã¿ãŒãäœæããååãšã»ã«ã³ããªåã®äž¡æ¹ãå«ããªããžã§ã¯ãã®å€ã確èªããŸãã 詳现ã«ã€ããŠã¯ããã®ã³ã¡ã³ããåç §ããŠãã ããã
ã¹ã¿ãŒã«é¢ããŠã¯...ãŸããããªãã®ã¢ãããŒãã¯ãããã¯ã²ã©ãèãã ããšããæå³ã§ãééã£ãŠãããããã§ã¯ãããŸããããããã¯ããªããŒã¿ãŒãçŸåšæ³å®ããŠããæ¹æ³ã§ã¯æ©èœããªãèãã§ãã ã§ããããããªãã®ã¢ãããŒãã¯ããã©ãŒã ãçŸåšã©ã®ããã«äœ¿çšããããšæ³å®ãããŠããããš_äºææ§ããªã_ãšèšãããã§ãã
説æããå¹æããã°ããå®çŸãããå Žåã¯ãç¬èªã®ãããã©ãŒã äœæã©ã€ãã©ãªãäœæããå¿
èŠããããŸãã ããã¯ããã®åé¡ã«çŽé¢ããå Žåã«åé¡ã«ã©ã®ããã«åãçµããã«ã€ããŠã®ç°¡åãªã¹ã±ããã§ãã ããšãã°ã次ã®ãããªspec
ãªããžã§ã¯ããåãå
¥ããé¢æ°createForm
ãäœæã§ããŸãã
spec = {
name: {
initialValue: '',
isRequired: (formValue) => true, // always required
},
secondName: {
initialValue: '',
isRequired: (formValue) => isFilledIn(formValue.name), // required only if name is filled in
}
isFilledIn
ã¯ãå€ãå
¥åãããŠãããã©ãããå€å¥ããé¢æ°ã§ãã ããããval => val != null && value != ''
ã®ãããªãã®ã§ãã
ãã®createForm
ã¯ã次ã®ããã«äœæããå Žåãšåããã©ãŒã ãè¿ããŸãã
this.fb.group({
name: [''],
secondName: [''],
}, {
validators: [
(group) => {
const value = group.value
const errors = {}
if (spec.name.isRequired(value) && !isFilled(value.name)) {
errors['name-required'] = true
}
if (spec.secondName.isRequired(value) && !isFilled(value.secondName)) {
errors['secondName-required'] = true
}
return errors // or null if no errors found
}
]
})
ãšã©ãŒã¯ã°ã«ãŒãèªäœã«çºçããŸãã secondName
ã®ãšã©ãŒã¯ç¢ºãã«ããã«å±ããŸãããã®æå¹æ§ã¯å¥ã®ãã£ãŒã«ãã«äŸåããããã secondName
ãåç¬ã§æ€èšŒããããšã¯ã§ããŸããïŒä»£ããã«ãããã®ãã£ãŒã«ãã®ã°ã«ãŒããæ€èšŒããŸãïŒã name
ã®ãšã©ãŒã¯$ name
ã«å±ããã¯ãã§ããããã®å®è£
ã®ã¹ã±ããã¯ããããã©ãŒã ã°ã«ãŒãã«é
眮ããŸãã ããã¯ããŸããããããããŸããããããŸããããªããããããŸããã spec
ãªããžã§ã¯ãã«ãã£ãŒã«ããå°å
¥ããŠããã®ããã«æ§æãããã«åŸ®èª¿æŽããããšãã§ããŸãã
@angular/forms
ãªããžã§ã¯ããæå
ã«ããã®ã§ããã³ãã¬ãŒãã§ã¯éåžžã©ãããã©ãŒã ã䜿çšããŸãã ãã©ãŒã ã°ã«ãŒãããã®ãšã©ãŒãšã³ã³ãããŒã«ããã®ãšã©ãŒïŒãŸãã¯ããããæ©èœããå Žåã¯ã°ã«ãŒãããã®ãã¹ãŠïŒãå°å·ããå¿
èŠããããŸãã ã¹ã¿ãŒãåãæ¿ããããã®æ¡ä»¶ã¯spec[key].isRequired(form.value)
ã«ãªããŸãã
ãããã©ãã ãæ£ç¢ºã«å®è£ ããããšããå¯èœæ§ã¯ç¡éã§ãããããã¯ãã¹ãŠããã©ãŒã APIããã¹ãŠã®äººãæºè¶³ããããšã¯æããªãã»ã©ã®å°ããªæ±ºå®ã«äŸåããŸãã ãããã£ãŠãèªåã®ãããžã§ã¯ãã§ãã©ãŒã ã«æåŸ ããå 容ã«å¿ããŠããã©ãŒã ãã«ããŒã®åšãã«ãã»ãã³ãã£ãã¯ãã©ãããŒãå°å ¥ããã®ãæåã§ããããã«ãããèŠä»¶ã«åºã¥ããŠè¿œå ã®åŠçãå®è¡ãããŸãã
ã¢ãããŒããšåã®ã³ã¡ã³ããåç §ããããã«æéãè²»ãããŠãããŠããããšããã¹ã¬ããã®æŽå²ã¯ããªãé·ãã§ã:)
ãããç§ã®åé¡ã®äžéšã ã£ããšæããŸãã ã°ã«ãŒãåãããã³ã³ãããŒã«ãšã°ã«ãŒãå€ã«ååšããã³ã³ãããŒã«éã®ãã£ãŒã«ãã®äŸåé¢ä¿ãé©åã«ç®¡çããŸãã ã¹ããã¯ã¢ãããŒãã¯ã»ãšãã©ã®åéã§ç§ã®ãã©ãŒã«ããã¯ã§ããã®ã§ãããªããããã«ã¢ãããŒãããæ¹æ³ã§ããããã«æããŠããããã§ãã
ãã©ãŒã APIããã¹ãŠã®äººãæºè¶³ããããšã¯æããªã
確ãã«ãæäŸãããŠããAPIããã®çš®ã®ã«ãã¬ããžãæºãããŠãããã©ããã¯ããããŸããã
ãã¹ãŠã®ã¢ããããŒãïŒ ãã®å·ã®äœæããã»ãŒ4幎ã
çŸåšãæ€èšŒãä¿åããããã®ã«ã¹ã¿ã ãŠãŒãã£ãªãã£é¢æ°ãäœæããŠããŸããããã¯ãformControlã®getValidatorsã®ããã ãã«ãããã©ãè§åºŠãã掟çããããé¢æ°ã§ãã
æ¬åœã«ãã®æ©èœãå¿ èŠã«ãªããŸã
ããã¯ããªã¢ã¯ãã£ããã©ãŒã ãã©ãããã䜿çšè ã«ãšã£ãŠéåžžã«åœ¹ç«ã¡ãŸã
éåžžã«è²Žéãªã¹ã¬ããã ãã ãããã©ãŒã ã³ã³ãããŒã«ã®ããªããŒã¿ãŒã«ã¢ã¯ã»ã¹ã§ããªãããã«ããããšã§ãã©ã®ãããªç®çã解決ããã®ãã«ã€ããŠå°ãæ··ä¹±ããŠããŸãã ç§ã¯ãã®èŠä»¶ã«ã¶ã€ãããŸãããã«ã¹ã¿ã ã³ã³ããŒãã³ããå¿ èŠãªå Žåã¯ã*ãã衚瀺ããå¿ èŠãããããã®ããäžã«é¢é£ãããšã©ãŒã¡ãã»ãŒãžã衚瀺ãããå¯èœæ§ããããŸãïŒãŠãŒã¶ãŒããããåžæããå ŽåïŒã ãã1ã€ã®æ¹æ³ã¯ããŠãŒã¶ãŒã«ãã³ãã¬ãŒãããããããã£ãèšå®ãããããšã§ãã³ã³ãããŒã«èªäœã®APIã«è¿œå ããããšã§ãã ãã ãããªã¢ã¯ãã£ã圢åŒã®å ŽåããŠãŒã¶ãŒãå¿ èŠãªããªããŒã¿ãŒïŒãŸãã¯ãã®ä»ã®ããªããŒã¿ãŒïŒãæ¢ã«æäŸããŠãããããããã¯å¿ èŠãããŸããã ç§ã®ã«ã¹ã¿ã ã³ã³ããŒãã³ãã¯ããã®ãããªããªããŒã¿ãŒãèšå®ãããŠããããšãèªèã§ããããã«åºã¥ããŠèŠçŽ ã衚瀺/é衚瀺ã«ã§ããã¯ãã§ãã éåžžã«äžè¬çãªèŠä»¶ã®ããã§ãã
ããªããŒã¿ãŒã«é¢ãããã¹ãŠã®æ å ±ãæã¡ããããã®ããªããŒã¿ãŒãå®å šã«å¶åŸ¡ã§ããããã«ããã«ã¹ã¿ã æ§æã®ã«ã¹ã¿ã FormControlã䜿çšãããœãªã¥ãŒã·ã§ã³ïŒ
export class CustomFormControl extends FormControl {
public listValidator: CustomValidator[] = [];
private constructor(formState?: any,
validatorOrOpts?: ValidatorFn | ValidatorFn[] | CustomCtrlOpts | null,
asyncValidator?: AsyncValidatorFn | AsyncValidatorFn[] | null) {
super(formState, validatorOrOpts as ValidatorFn[], asyncValidator);
if (validatorOrOpts instanceof CustomCtrlOpts) {
this.listValidator = validatorOrOpts.customConf;
}
}
// Builder ith default value
public static init(formState?: any): CustomFormControl {
return new CustomFormControl(isNil(formState) ? null : formState);
}
public required(): CustomFormControl {
return this.and('required');
}
public email(): CustomFormControl {
return this.and('email');
}
public custom(): CustomFormControl {
return this.and('custom');
}
public min(min: number): CustomFormControl {
return this.and('min', min);
}
public max(max: number): CustomFormControl {
return this.and('max', max);
}
private and(key: TypeCustomValidator, value?: any): CustomFormControl {
this.listValidator.push({key: key, value: value});
this.setValidators(new CustomCtrlOpts(this.listValidator).validators as ValidatorFn[]);
return this;
}
}
// Add others if needed
export type TypeCustomValidator = 'min' | 'max' | 'required' | 'email' | 'custom' ;
export interface HandledValidator {
key: TypeCustomValidator;
function: Function;
params?: boolean;
}
export const listHandledValidators: HandledValidator[] = [
{key: 'required', function: Validators.required},
{key: 'email', function: Validators.email},
{key: 'min', function: Validators.min, params: true},
{key: 'max', function: Validators.max, params: true},
{key: 'custom', function: custom}
];
export interface CustomValidator {
key: TypeCustomValidator;
value?: any;
}
export class CustomCtrlOpts implements AbstractControlOptions {
validators?: ValidatorFn | ValidatorFn[] | null;
asyncValidators?: AsyncValidatorFn | AsyncValidatorFn[] | null;
updateOn?: 'change' | 'blur' | 'submit';
private _customConf?: CustomValidator[];
constructor(value: CustomValidator[]) {
this.customConf = value;
}
get customConf(): CustomValidator[] {
return this._customConf;
}
set customConf(value: CustomValidator[]) {
this._customConf = value;
if (!value) {
return;
}
this.validators = [];
value.forEach(customValidator => {
const validator = listHandledValidators.find(it => it.key === customValidator.key);
if (validator.params) {
(this.validators as ValidatorFn[]).push(validator.function(customValidator.value) as ValidatorFn);
} else {
(this.validators as ValidatorFn[]).push(validator.function as ValidatorFn);
}
});
}
}
次ã®ãããªformGroupåæåã䜿çš
this.form = this.fb.group({
amount: CustomFormControl.init(10).required().min(0),
...
ããã¯æ¬åœã«çŽ æŽãããæ©èœã§ãã ãã®ããã®åé¿çã䜿çšãããšãæéã®ç¡é§ã®ããã«æããŸãã
æ¬åœã«ãã®æ©èœãå¿ èŠã«ãªããŸã
ãããããã¯æ¬åœã«å¿ èŠã§ãã ç°¡åã«èšãã°ãäœããèšå®ããæ¹æ³ããããšãããããããç¡å¹ã«ããåæ§ã®æ¹æ³ãããã¯ãã§ãã äœããç°¡åã«èšå®ã§ããããããããåãæ»ãããã«å€ãã®åŽåãè²»ãããªããã°ãªããªãå Žåã_æ¬åœã«å¿ èŠãª_äœããæããã«æ¬ ããŠããŸãã
ãã®åé¡/æ©èœã«é¢ããé²å±ã¯ãããŸããïŒ
@BenKatanHighLanderéäžã§ãïŒ https ïŒ//github.com/angular/angular/pull/37263#issuecomment -723333060
æãåèã«ãªãã³ã¡ã³ã
ç§ã¯åæããŸããçŸåšã®ã³ã³ãããŒã«ã®ã¡ãœããã§ååŸã§ããããªããŒã¿ãŒã®èªã¿åãå°çšãªã¹ãããããšéåžžã«åœ¹ç«ã¡ãŸãã