The value [value] is not assigned in input - html

I have a little problem using [value] in my inputs.
This is my component .html
<div class="form-group">
<mat-form-field class="example-full-width" style="padding-left: 15px;">
<input matInput [value]='value_2_' [(ngModel)]="form.name_1" placeholder="name_1"
name="name_pro_1" required>
</mat-form-field>
</div>
Everything looks good, but when I run the program, the value is shown in the corresponding input, however, being a value required by the input, it is still in red, it is solved until I add a letter to the value or remove something from the input.
I managed to solve the error by deleting
name = "name_pro_1"
but since I use NgModel I cannot remove the name because I get other errors. Like:
core.js:4352 ERROR Error: If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.
Example 1: <input [(ngModel)]="person.firstName" name="first">
Example 2: <input [(ngModel)]="person.firstName" [ngModelOptions]="{standalone: true}">

I think the problem is [(ngModel)]="form.name_1". Try to replace that with
[(ngModel)]="testValue" and define a variable in the class with the same name and it will work.

I can't replicate the problem, but using [(ngModel)] doesn't make using [value] unnecessary? You can set the form.name_1 to the value you want on the component.ts file.

Finally i resolved the issue, that it's my solution:
First thing first, i delete the [(ngModel)] in the input of component.html, then i used (change) to call the function when user select a SKU
<div class="form-group input-sku" >
<mat-form-field class="example-full-width">
<mat-label>SKU</mat-label>
<input type="text" placeholder="Search.." id="sku_select" aria-label="number"
matInput [formControl]="myControl" [matAutocomplete]="auto"
[(ngModel)]="selectedValue" (change)="changedata_1($event)" >
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
<mat-option *ngFor="let data of filter_products | async" [value]="data.sku">{{data.sku}}</mat-option>
</mat-autocomplete>
</mat-form-field>
</div>
Input who recived the value:
<div class="form-group inputs-name">
<mat-form-field class="example-full-width">
<mat-label>Name</mat-label>
<input type="text" matInput id="nombre_1" required [value]="name_1" name="name_1" placeholder="Name" >
</mat-form-field>
</div>
And in my component.ts
changedata_1(e) {
this.nombre_1 = e.target.value;
this.DataToSave.nombre_1 = this.nombre_1;}
private _filter(value: string): Products_BD[] {
const filterValue = value.toLowerCase();
const data_ = this.DatasProducts.filter(DataProducts => DataProducts.sku.toLowerCase().includes(filterValue));
for(let element of data_){
const sku1= elemento.sku;
const name1 = element.name;
this.name_1 = name1;
this.DataToSave.sku_1 = sku1;
this.DataToSave.name_1 = name1;
}
return this.DataProducts.filter(DataProducts => DataProducts.sku.toLowerCase().includes(filterValue));}
this.filter_products = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value))
);
I hope this solution helps! :)

Related

patchValue not working when using [[ngModel]]

So when I open an item editor dialog, I want to be able to put some default values that I retrieve from the specific item I selected. This all worked up until I added [[ngModel]] in each of the fields. In fact, it still works when I remove it. I want to be able to do it again without removing the ngModel as I heavily depend on it in my code.
This is my HTML
<div mat-dialog-content class="formCentered">
<form [formGroup]="form">
<mat-form-field class="inputBox">
<mat-label>Scanner</mat-label>
<input matInput formControlName="scannerName" [(ngModel)]="data.scanName" maxlength="50">
</mat-form-field>
<mat-form-field class="inputBox">
<mat-label>Calibration Price</mat-label>
<input matInput formControlName="calibrationPrice" [(ngModel)]="data.caliPrice" maxlength="50">
</mat-form-field>
<mat-form-field class="inputBox">
<mat-label>Calibration Description</mat-label>
<input matInput formControlName="calibrationDescription" [(ngModel)]="data.caliDescription" maxlength="50">
</mat-form-field>
</form>
</div>
<div mat-dialog-actions class="alignRight">
<button mat-button class="confirmationButton" (click)="onNoClick()" class="confirmationButton">Cancel</button>
<button mat-button class="confirmationButton" [mat-dialog-close]="data" cdkFocusInitial class="confirmationButton">Save</button>
</div>
And this is my part of the ts for this
dialogRef.componentInstance.form.patchValue({
scannerName: cal.scannerName, // scannerName is the old value (unedited)
calibrationPrice: cal.calibrationPrice, // calibrationPrice is the old value (unedited)
calibrationDescription: cal.calibrationDescription // calibrationDescription is the old value (unedited)
});
Any idea on how I can achieve that?
It's not a good practice merge reactive forms with ngModel.
You can remove all of the [(ngModel)] in the html, and subscribe to the form changes. Then, when some field of the form change, the subscription would change your varaibles as well.
Add in your ts code something like this:
// after you have inicialized your form
this.form.get('scannerName').valueChanges
.subscribe((val: any) => {
//this.data.scanName = this.form.get('scannerName').value;
this.data.scanName = val
});
this.form.get('calibrationPrice').valueChanges
.subscribe((val: any) => {
//this.data.calibrationPrice= this.form.get('calibrationPrice').value;
this.data.calibrationPrice= val
});
this.form.get('calibrationDescription').valueChanges
.subscribe((val: any) => {
//this.data.calibrationDescription= this.form.get('calibrationDescription').value;
this.data.calibrationDescription= val
});
You can't add NgModel in formGroup.
You have to define the formControl
example:
form = new FormGroup({
scannerName: new FormControl(''),
calibrationPrice: new FormControl(''),
calibrationDescription: new FormControl(''),
})
If you want set default value, you have to set value in new FormControl like this:
form = new FormGroup({
scannerName: new FormControl('test'),
calibrationPrice: new FormControl('value'),
calibrationDescription: new FormControl(someValue),
})
it's seems that you want change data variable, you could do this:
this.data = this.form.value

How to disable a text area or mat-form-field in the same HTML (Angular 9)

I am using Angular 9 with angular Material Reactive Forms. I want to disable the fields, but without using the disabled status on the formControl, just only using HTML instead of programmatically in ts.
My Html:
<form name="nameForm" [formGroup]="nameForm" fxLayout="column">
<mat-form-field fxFlex="50" class="m-4">
<input matInput name="startTime" formControlName="startTime" placeholder="{{'DATE.START' | translate}}" type="date">
</mat-form-field>
<mat-form-field fxFlex="30" class="m-4">
<input matInput name="period" formControlName="period" placeholder="{{'TITLE.PERIOD' | translate}}" type="number" step="0.1">
</mat-form-field>
<mat-form-field fxFlex="20" class="m-4">
<input matInput name="range" formControlName="range" placeholder="{{'TITLE.RANGE' | translate}}" type="number" step="0.1">
</mat-form-field>
</form>
My ts:
ngOnInit(): void {
this.nameForm = this.createNameForm();
... some code ...
}
private createNameForm() {
return this.formBuilder.group({
startTime: new FormControl(this.startTime, []),
period: new FormControl(this.period, []),
range: new FormControl(this.range, []),
});
}
... some code ...
I came across this doubt because some questions like this one (How to disable a text area or mat-form-field) has programmatic answers, and I would like to know if it can be solved using exclusively the Html. I know [disabled]="true" does not work, but maybe with a different directive?.
I hope it's clear enough and thanks in advance.
I think that the disabled directive is not valid for the input (it would work with a select or text-area for example ) but to disable the input we can use the readonly directive
[readonly]="true"
[readonly]="method()"
[readonly]="variable"
Although, if you need to disable it, another solution would be
[attr.disabled]="true"
[attr.disabled]="method()"
[attr.disabled]="variable"
I've tried both and they work :)
I have tried both the [disabled] = 'true' and [readonly] = 'true' for the textarea.
Only [readonly] property works well in all the cases in angular.

formGroup expects a FormGroup instance. Please pass one in. How to fix this error?

My HTML source code as follows,
<p>
<mat-form-field appearance="legacy" [formGroup]="form" (submit)="onFormSubmit()">
<mat-label>Add a List</mat-label>
<input [(ngModel)]="listName" matInput placeholder="Placeholder" formControlName="name" #nameInput fxFlex>
<mat-icon matSuffix class="check" (click)="onFormSubmit()">check</mat-icon>
<mat-icon matSuffix class="clear" (click)="closeForm()">clear</mat-icon>
</mat-form-field>
</p>
when running this code following error shows on the console,
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
how can I fix this error?
Typo ? You wrote:
[formGroup]="form"
It should be:
[formGroup]="myGroup"

Template Driven Form Mark All as touched - Angular 7

I am using template driven forms for validations. And I would like to Mark all fields as touched when the user blur on the last required field. currently I am only able to do this by passing the form and individually doing each field. From research I see there is a way to do MarkAllAsTocuhed but it's throwing an error. Is there a better/correct way to do this with Angular 7. I also tried looping through the controls but since it's an object that also does not work.
.HTML
<form #myForm="ngForm">
<mat-form-field class="input-field">
<input #field1="ngModel" name="name1"
[(ngModel)]="fieldOne" type="text" matInput placeholder="Field 1" required>
</mat-form-field>
<mat-form-field class="input-field">
<input #field2="ngModel" name="name2"
[(ngModel)]="fieldTwo" type="text" matInput placeholder="Field 2" required>
</mat-form-field>
<mat-form-field class="input-field">
<input #field2="ngModel" name="name3"
[(ngModel)]="fieldThree" type="text" matInput placeholder="Field 3" required>
</mat-form-field>
<mat-form-field class="input-field">
<input #field3="ngModel" name="name4"
[(ngModel)]="fieldFour" type="text" matInput placeholder="Field 4"
(blur)="touchAllFields(myForm.form)" required>
</mat-form-field>
</form>
.TS
touchAllFields(form){
//Working Version
form.controls.name1.markAsTouched();
form.controls.name2.markAsTouched();
form.controls.name3.markAsTouched();
form.controls.name4.markAsTouched();
form.controls.name5.markAsTouched();
form.controls.name6.markAsTouched();
form.controls.name7.markAsTouched();
form.controls.name8.markAsTouched();
//Failed Attempt
form.controls.markAllAsTouched(); //typeError: form.controls.markAllAsTouched is not a function
//Failed Attempt
for(var i = 0; i < form.controls.length; i++){
form.controls[i].markAllAsTouched(); //Failed since its an object and not an array
}
}
ngForm itself has no markAllAsTouched method since it's not a FormGroup or FormArray. However, NgForm has an instance of a formGroup accessible via .form or .control - source.
This has been available since Angular2 until the current latest version (Angular10)
So the correct answer to your questions should be as follows:
form.form.markAllAsTouched();
or
form.control.markAllAsTouched();
You can try this:
Found out that Object.keys can handle this.
Object.keys(this.form.controls).forEach(key => {
this.form.get(key).markAsTouched();
});
For Angular 8+, you can use:
Object.keys(this.form.controls).forEach(key => {
this.form.controls[key].markAsTouched();
});

Reset Angular Formly Form Validations on click event

I am implementing dynamic forms using the angular formly module and It's working fine. What functionality I need is Initially there should be a select box which contains multiple options, Based on selection different form fields should be displayed. As I explained I have Implemented and it's working, here what my problem is If I select option 1 and If I submit the form without filling fields, form displaying validation errors that is also cool. But when I select option 2 form fields are changing, but by default, all required fields are showing errors. How can I resist this? Please suggest me.
html
<div class="row">
<mat-form-field class="col-lg-2">
<mat-select placeholder="Form For" (selectionChange)="getSelectedFormName($event)">
<mat-option value="uf001">UF001</mat-option>
<mat-option value="uf002">UF002</mat-option>
<mat-option value="uf003">UF003</mat-option>
</mat-select>
</mat-form-field>
<div class="col-lg-4">
<button type="button" class="btn btn-default btn-one" (click)="getDynamicForm()">GET FORM</button>
</div>
</div>
<form [formGroup]="form" (ngSubmit)="submit(model)" >
<formly-form [model]="model" [fields]="fields" [form]="form" *ngIf="isFormTypeSelected" >
</formly-form>
<button type="submit" class="btn btn-success">Submit</button>
</form>
ts file
getSelectedFormName(eve) {
this.isFormSaved = false;
this.form = new FormGroup({});
this.fields=[];
this.model = {};
this.parentFormName = eve.value;
}
getDynamicForm() {
this.isFormSaved = false;
this.savedFields=[];
this.getDynamicFormBasedOnSelection(this.parentFormName);
//fields getting from api call
}
getDynamicFormBasedOnSelection(formName: string) {
this.auth.getDynamicFormBasedOnSelction(formName, this.userAgencyCode).subscribe(
(result) => {
const str = JSON.stringify(result);
this.fields = JSON.parse(str);
this.isFormTypeSelected = true;
this.addEvents(this.fields);
});
}
Here I'm providing my screens which are for better understanding
Actually form.reset() just reset the form values. You need to reset the form directive too. for eg.
<form [formGroup]='authForm' (submit)='submitForm(formDirective)' #formDirective="ngForm" class="is-mat-form">
<mat-form-field>
<input matInput placeholder="Email ID" formControlName='login'>
<mat-error *ngIf="authForm.controls.login.hasError('required')">
Email is required
</mat-error>
<mat-error *ngIf="authForm.controls.login.hasError('email')">
Please enter a valid email address
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" formControlName='password' placeholder="Password">
<mat-error *ngIf="authForm.controls.password.hasError('required')">
Password is required
</mat-error>
<mat-error *ngIf="authForm.controls.password.hasError('minlength')">
Password must be minimum 6 digit long.
</mat-error>
</mat-form-field>
and .ts file is
submitForm(formDirective: FormGroupDirective){
if (this.authForm.invalid) {
console.log('form submitted')
this.authForm.reset()
return;
}
this will reset the form values only, to reset the form error we need to reset the formdirective as well.
submitForm(formDirective: FormGroupDirective){
if (this.authForm.invalid) {
console.log('form submitted')
this.authForm.reset()
formDirective.resetForm();
return;
}