Reputation: 1
I have the following component in html and I simply try to pass input value to the component:
<mat-accordion class="example-headers-align">
<mat-expansion-panel [expanded]="expanded" hideToggle>
<mat-form-field *ngIf="expanded">
<input #empName matInput type="text" formControlName="empName"/>
</mat-form-field>
</mat-expansion-panel>
<button *ngIf="expanded" mat-button (click)="add(empName.value)">Add</button>
</div>
</mat-accordion>
However, the value is undefined in the component method and even I try to pass empName
, instead of empName.value
the parameter is also undefined. So, what is the mistake in this approach? How can I pass the input value without using [(ngModel)]
?
add(data) { // data --> undefined
this.add.emit(data)
}
I also get "Cannot read property 'value' of undefined" error on <button *ngIf="expanded" mat-button (click)="add(empName.value)">Add</button>
.
Upvotes: 1
Views: 1014
Reputation: 1102
What you are doing is perfectly valid but you have not taken into consideration the scope of the template variables.
Using structural directives creates scopes/boundaries which block the usage of those variables, as you can see there: https://angular.io/guide/template-reference-variables#template-variable-scope
So to solve your problem in the way you want you need to work on your template and remove the usage of the *ngIf
s
The following code which just omits the *ngIf
s works as you'd expect it to (naturally this is not a complete solution since your component without the *ngIf
s just behaves differently from what you wanted):
<div>
<mat-accordion class="example-headers-align">
<mat-expansion-panel [expanded]="false" hideToggle>
<mat-form-field>
<input #empName matInput type="text" formControlName="empName" >
</mat-form-field>
</mat-expansion-panel>
<button mat-button (click)="add(empName.value)">Add</button>
</mat-accordion>
</div>
You can check it out in this stackblitz project: https://stackblitz.com/edit/angular-ivy-c64ppz?file=src/app/app.component.html (please ignore the console errors on the material components, those are not the point here :P)
One thing that would change your code in the smallest degree but allow you to keep your implementation could be to avoid the *ngIf
s but hide the elements via css instead, as in the following:
Template:
<div>
<mat-accordion class="example-headers-align">
<mat-expansion-panel [expanded]="expended" hideToggle>
<mat-form-field [ngClass]="{'hidden': !expanded}">
<input #empName matInput type="text" formControlName="empName" >
</mat-form-field>
</mat-expansion-panel>
<button [ngClass]="{'hidden': !expanded}" mat-button (click)="add(empName.value)">Add</button>
</mat-accordion>
</div>
css:
.hidden {
display: none;
}
Again here's a stackblitz in which you can see it working: https://stackblitz.com/edit/angular-ivy-iamrut?file=src/app/app.component.html
Upvotes: 1
Reputation: 2078
You are using formControlName
with reactive forms, so if you want to access the value of this fields, then you have to access it from the formGroup
form object.
Something like this:
employeeForm: FormGroup;
and the value of the form fields you can acess like this:
employeeForm.value.empName
So in your function try to pass value like this:
<button *ngIf="expanded" mat-button (click)="add(employeeForm.value.empName)">Add</button>
Upvotes: 1
Reputation: 107
In your html file
<mat-accordion class="example-headers-align">
<mat-expansion-panel [expanded]="expanded" hideToggle>
<mat-form-field *ngIf="expanded">
<input matInput type="text" [formControl]="empName"/>
</mat-form-field>
</mat-expansion-panel>
<button *ngIf="expanded" mat-button (click)="add()">Add</button>
</div>
</mat-accordion>
In your ts file
empName = new FormControl('');
add() { // remove the parameter
// this.add.emit(data), try if it is working first
console.log(this.empName);
}
Hope it helps.
Happy Coding!
Upvotes: 2