Dynamic Validation with nested form - javascript

I'm trying to create a nested form with dynamic validation. There's the parent component (finalizaNegociacao) which hold the nested forms (dadosTitular). On the nested form I have a checkbox (handleType) that changes the validation of some fields, like cpf. What should be happening is: When I click on the checkbox cpfis no longer a required field. But even if I click on it it still required. Can someone help me?
Here's the code:
FinalizaNegociacao (parent component), the main logic here is in the recebeValidators :
export class FinalizaNegociacaoComponent implements OnInit, OnChanges {
public dados:dadosAcordo;
public formDadosBancarios: FormGroup;
public submitted: boolean;
public events: any[] = [];
public servError:any;
public servSuccess:any;
cpf_REGEXP = /^\d+$/;
constructor(private _fb: FormBuilder, private finalizaAcordo:FinalizaNegociacaoService) {}
ngOnInit() {
this.formDadosBancarios = this._fb.group({
id: [''],
dados_titular: this._fb.array([
this.initTitular()
])
})
}
initTitular(){
return this._fb.group({
titular: ['', [<any>Validators.required, <any>Validators.minLength(3)]],
cnpj: [''],
cpf: ['', <any>Validators.required],
data_nasc: [''],
agencia: ['', <any>Validators.required ],
banco: ['', <any>Validators.required],
conta: ['', <any>Validators.required],
tipo: ['', <any>Validators.required],
pessoa_juridica: ['']
})
}
addTitular(){
const control = <FormArray> this.formDadosBancarios.controls['dados_titular'];
control.push(this.initTitular());
}
recebeValidators(e:any){
let array = <FormArray> this.formDadosBancarios.get('dados_titular');
let cpf = array.at(0).get("cpf");
let cpfCtrl = this.formDadosBancarios.get(['dados_titular',0,'cpf']);
let cnpj = array.at(0).get('cnpj');
let data_nasc = array.at(0).get('data_nasc');
cpfCtrl = e;
console.log(cpfCtrl);
}
DadosTitular, (Child component), the main logic here is the handleType:
export class TitularComponent {
// we will pass in address from App component
#Input('group')
public titularForm: FormGroup;
#Output() modelChanged = new EventEmitter();
public formDadosBancarios: FormGroup;
cpf_REGEXP = /^\d+$/;
constructor(private _fb: FormBuilder, private finalizaAcordo:FinalizaNegociacaoService) {}
ngOnInit() {
this.formDadosBancarios = this._fb.group({
id: [''],
dados_titular: this._fb.array([
this.initTitular()
])
})
}
initTitular(){
return this._fb.group({
titular: ['', [<any>Validators.required, <any>Validators.minLength(3)]],
cnpj: [''],
cpf: ['', <any>Validators.required],
data_nasc: [''],
agencia: ['', <any>Validators.required ],
banco: ['', <any>Validators.required],
conta: ['', <any>Validators.required],
tipo: ['', <any>Validators.required],
pessoa_juridica: ['']
})
}
handleType(isJuridica: boolean, i:number, e:any): void {
let array = <FormArray> this.formDadosBancarios.get('dados_titular');
let cpf = array.at(0).get("cpf");
let cnpj = array.at(0).get('cnpj');
let data_nasc = array.at(0).get('data_nasc');
const cpfCtrl = this.formDadosBancarios.get(['dados_titular',0,'cpf']);
const cnpjCtrl = this.formDadosBancarios.get(['dados_titular',0, 'cnpj']);
const data_nascCtrl = this.formDadosBancarios.get(['dados_titular',0,'data_nasc']);
const reqValidators: ValidatorFn[] = [Validators.required, Validators.pattern(this.cpf_REGEXP)];
if (isJuridica) {
cpfCtrl.setValidators(null);
data_nascCtrl.setValidators(null);
cnpjCtrl.setValidators(reqValidators);
this.modelChanged.emit(cpfCtrl);
}else{
cpfCtrl.setValidators(reqValidators);
data_nascCtrl.setValidators(reqValidators)
cnpjCtrl.setValidators(null);
this.modelChanged.emit(cpfCtrl);
}
cpfCtrl.updateValueAndValidity();
data_nascCtrl.updateValueAndValidity();
cnpjCtrl.updateValueAndValidity();
}
}
and there's the html:
<div formArrayName="dados_titular">
<div *ngFor="let dados_titular of formDadosBancarios.controls.dados_titular.controls; let i=index">
<div [formGroupName]="i">
<titular (modelChanged)="recebeValidators($event)" [group]="formDadosBancarios.controls.dados_titular.controls[i]"></titular>
</div>
</div>
</div>

Related

Problem with storing data in Firebase (_isScalar: false)

I have created a form that stores the course type data in the Firebase. When I try to save a new element it creates this: https://i.stack.imgur.com/jXO1z.jpg.
Here's my code in create-course Component:
form: FormGroup = this.fb.group({
name: [''],
code: [''],
ects: [''],
lekt: ['']
})
constructor(private fb: FormBuilder, private dataStorageService : DataStorageService) { }
ngOnInit(): void {}
onSaveData(){
this.dataStorageService.storeCourses();
}
Here's the code in the service component :
storeCourses(){
const courses = this.courseService.getCourses();
this.http.put(
'https://projekti-ff52b-default-rtdb.firebaseio.com/courses.json',
courses)
.subscribe(response => {
console.log(response);});
}
getCourses() {
return of(this.courses); }
private courses: Course[] = [];
And Course [] is an exported interface from course model.ts

Why does using a form input rather than static string prevent my code from generating a qr code?

Trying to pass a text input value from my form to a JS library to process a qr code does not work. Adding a static value works all the time. How do I make it so that the value from my form works. For example making text = "2743987947" or text = text = "hello" works.
Console logging the input value gives me the correct value. However using this value to create a qr code fails.
Here is my code.
export class HomeComponent implements OnInit {
designForm: FormGroup;
printForm: FormGroup;
qrcodeImage;
load: boolean;
constructor(private formBuilder: FormBuilder) {}
ngOnInit() {
this.designForm = this.formBuilder.group({
model: ['', Validators.compose([Validators.required])],
color: [
'',
Validators.compose([
Validators.required,
Validators.pattern('[\\w\\-\\s\\/]+'),
]),
],
space: ['', Validators.compose([Validators.required])],
serial1: ['', Validators.compose([Validators.required])],
serial2: ['', Validators.compose([Validators.required])],
});
this.printForm = this.formBuilder.group({
name: [
'',
Validators.compose([
Validators.required,
Validators.pattern('Martin Tecno'),
]),
],
});
this.qrcodeImage = this.createQrcode();
}
createQrcode() {
let text = this.designForm.value.serial1;
let typeNumber = 4;
let errorCorrectionLevel = 'H';
let qr = qrcode(typeNumber, errorCorrectionLevel);
qr.addData(text);
qr.make();
// return qr.createTableTag();
// return qr.createSvgTag();
return qr.createImgTag();
}
onSubmit(designForm) {
console.log(designForm);
console.log(this.qrcodeImage);
console.log(this.designForm.value.serial1);
}
}```

PatchForm not working after api call Angular 8

i am using patch value to update my form but i am unable to do that, my view is not getting updated , though i have tried both approaches async/await and observable. Although i found a workaround by using set timeout but that is not a proper solution.
Thanks in advance.
Approach 1 using arrow function and async/await (promise)
constructor(
public storage: Storage,
public route: Router,
public navCtrl: NavController,
public toastController: ToastController,
public alertController: AlertController,
public loadingController: LoadingController,
public formBuilder: FormBuilder,
public dataInteractionService: DataInteractionService,
public router: ActivatedRoute
) {
super(storage, route, navCtrl, toastController, alertController, loadingController);
this.initialize_Sub_for_Param();
}
initialize_Sub_for_Param() {
this.router.queryParams.subscribe(params => {
debugger;
this.initialize_Form();
if (this.route.getCurrentNavigation().extras.state) {
debugger;
this.petDetails = this.route.getCurrentNavigation().extras.state.user;
console.log(this.petDetails, "petDetails")
this.get_Data_animal(this.petDetails);
}
});
}
ngOnInit() {}
initialize_Form() {
this.edit_animal_Form = this.formBuilder.group({
animal_image: ['', Validators.required],
animal_name: ['', Validators.required],
species_id: ['', Validators.required],
breed_id: ['', Validators.required],
date_of_birth: ['', Validators.required],
electronic_number: ['', Validators.required],
})
}
get_Data_animal = async (form_Value) => {
try {
let breed_Species_data = await this.dataInteractionService.get_Animal_Spcices().toPromise();
this.get_species = breed_Species_data['species'];
this.get_breeds = breed_Species_data['breeds'];
debugger;
//Workaround using settimeout but i know this is not a proper sollution//
setTimeout(() => {
this.edit_animal_Form.patchValue(form_Value);
console.log(this.edit_animal_Form.value);
}, 100);
} catch (error) {
console.log(error)
}
}
Approach 2 using observables
constructor(
public storage: Storage,
public route: Router,
public navCtrl: NavController,
public toastController: ToastController,
public alertController: AlertController,
public loadingController: LoadingController,
public formBuilder: FormBuilder,
public dataInteractionService: DataInteractionService,
public router: ActivatedRoute
) {
super(storage, route, navCtrl, toastController, alertController, loadingController);
this.initialize_Sub_for_Param();
}
initialize_Sub_for_Param() {
this.router.queryParams.subscribe(params => {
this.initialize_Form();
if (this.route.getCurrentNavigation().extras.state) {
this.petDetails = this.route.getCurrentNavigation().extras.state.user;
this.get_Data_animal(this.petDetails);
}
});
}
ngOnInit() {}
initialize_Form() {
this.edit_animal_Form = this.formBuilder.group({
animal_image: ['', Validators.required],
animal_name: ['', Validators.required],
species_id: ['', Validators.required],
breed_id: ['', Validators.required],
date_of_birth: ['', Validators.required],
electronic_number: ['', Validators.required],
})
}
get_Data_animal = async (form_Value) => {
try {
this.dataInteractionService.get_Animal_Spcices().subscribe(res => {
this.get_species = breed_Species_data['species'];
this.get_breeds = breed_Species_data['breeds'];
this.edit_animal_Form.patchValue(form_Value);
});
} catch (error) {
console.log(error)
}
}
I have no idea what is going on in your code. But here is a fair example which i use to patch values in my form. I can give you the basic concept. Patch your form right after when you receive the values. For example:
getOrderById(id) {
this._order.getOrderWithId(id).subscribe((res: any) => {
this.orderForm.patchValue(res);
});
}
In this case you dont have to use setTimeout or any other async await stuff.

Add/ remove custom validators to form array in angular 8

Hi I am trying to set/ take away custom validators for different elements in a form array that can change around, so far what I have tried to do is create a switch statement and loop through all of the input types that are set so I could set the validation rule as well as send a message to the user if the rule isn't met. The problem I am having is the form is initialized before the form data is set.
So my question is how can I loop through the array and set the validation rules. If someone could let me know if im along the right tracks with using a switch statement but have code in the wrong place or if there is a different and better approach it would be most helpful thank you
export class ReactiveComponent implements OnInit {
public form: FormGroup;
public fieldList: any;
types: Array<any>;
formData: any;
Param: string;
setData: any;
formLabelNames: any;
get contactFormGroup() {
return this.form.get('inputs') as FormArray;
}
constructor(
private route: ActivatedRoute,
private fb: FormBuilder,
private api: FormService,
private notifiy: NotificationService,
private auth: AuthService,
private router: Router) { }
ngOnInit() {
this.form = this.fb.group({
name: ['', Validators.compose([Validators.required])],
organization: ['', Validators.compose([Validators.required])],
inputs: this.fb.array([this.createForm()])
});
this.route.paramMap.subscribe(params => {
this.Param = params.get('id');
this.getForm(this.Param);
});
// set fieldslist to this field
this.fieldList = this.form.get('inputs') as FormArray;
}
// formgroup
createForm(): FormGroup {
return this.fb.group({
type: ['', Validators.compose([Validators.required])],
name: ['', Validators.compose([Validators.required])],
value: ['', this.validators()]
});
}
getForm(id) {
this.api.getForm(id).subscribe(
(data: any) => this.setForm(data)
);
}
getFieldsFormGroup(index): FormGroup {
const formGroup = this.fieldList.controls[index] as FormGroup;
return formGroup;
}
getContactsFormGroup(index): FormGroup {
const formGroup = this.fieldList.controls[index] as FormGroup;
return formGroup;
}
setForm(data) {
const d = data.results;
this.setData = d;
this.formLabelNames = d[0].fields;
this.form.patchValue({
name: [d[0].form_name],
organization: [d[0].org],
});
this.form.setControl('inputs', this.setExistingFields(d[0].fields));
}
setExistingFields(fields: any): FormArray {
const formArray = new FormArray([]);
this.fieldList = formArray;
fields.forEach(f => {
formArray.push(this.fb.group({
name: f.name,
type: f.type,
value: f.value
}));
});
return formArray;
}
/* This is where I have tried to create a switch statement but I get a undefined error because the setform function is being called after this one */
validators() {
this.formLabelNames.type.forEach((field: any) => {
switch (field.type) {
case 'email':
}
});
}
submit() {
if (this.form.valid) {
const formId = this.Param;
const local = this.auth.decodePayload();
const userId = local.sub;
this.router.navigateByUrl('/dashboard');
this.api.sendForm(this.form.value, formId, userId).subscribe();
this.form.reset();
} else {
this.notifiy.showFailure('Form is not valid', 'Error');
}
}
}
You have several problems, as far as I can judge:
You don't initialize neither the formControls nor the formArray correctly inside of you formGroup. It should rather look like this:
this.form = this.fb.group({
name: new FormControl( "", {validators: [Validators.required]}),
organization: new FormControl( "", {validators: [Validators.required]}),
inputs: this.fb.array([new FormControl(), new FormControl()]),
});
Besides: What is the point of using a formArray when it consists of only one formGroup?
Off course you can set the validators for any abstractControl be it a formControl or a formGroup. For the array it would look like something like this:
this.formArray.controls.map((ctrl) => {
ctrl.setValidators([Validators.required, Validators.email]);
});
It doesn't matter where in the component class you put your method. Though it surely matters when that method is invoked!

Custom Validation with parameter

I am using Ionic 2 with Angular 2 beta 11.
I have a custom validator that works perfectly. However, I now need to add another custom validation method, but can't seem to work out how to pass a parameter to it.
As you can see below, I have a custom validation function:
ValidationService.userNameExists(control, this.employeeService)
'control' does not exist
How do I pass the control (FormControl) to the userNameExists function? Or, I need to pass the field value (value of username).
Thanks
register.ts
constructor(private nav: NavController, private builder: FormBuilder, employeeService: EmployeeService) {
this.employeeService = employeeService;
this.registerForm = builder.group({
'username': ['', [Validators.required, Validators.minLength(5), Validators.maxLength(55), ValidationService.userNameValidator, ValidationService.userNameExists(control, this.employeeService)]],
'password1': ['', [Validators.required, Validators.minLength(5), Validators.maxLength(45), ValidationService.passwordValidator]],
'password2': ['', [Validators.required, Validators.minLength(5), Validators.maxLength(45), ValidationService.passwordValidator]]
}, { 'validator': ValidationService.matchPassword('password1', 'password2') }
);
}
'control' does not exist
ValidationService.ts
public static userNameExists(control: FormControl, employeeService: EmployeeService): any {
return (control: FormControl) => {
let userNameInput = control.value;
console.log('userNameExists: '+control.value);
let promise: Promise<EmployeeModel> = employeeService.getEmployeByUserName(userNameInput);
promise.then((employeeModel: EmployeeModel) => {
if (employeeModel.userName === userNameInput) {
return { userNameExists: true };
} else {
return null;
}
});
}
}
Remember that when you are instantiating FormControl/FormGroup, you are passing the validation function in, not calling it. Change your username declaration as following:
'username': ['',
[Validators.required,
Validators.minLength(5),
Validators.maxLength(55),
ValidationService.userNameValidator,
(control) => ValidationService.userNameExists(control, this.employeeService)]]

Categories