I am passing in an object as my value and need to use [ngValue] as opposed to [value].
My HTML looks like this:
<mat-input-container fxFlex="18" fxFlexOffset="1">
<input
matInput
placeholder="Example"
[matAutocomplete]="autocomplete"
[ngModel]="user?.UserName"
(ngModelChange)="filter($event)"
[disabled]="disabled"/>
<mat-autocomplete #autocomplete="matAutocomplete"
(optionSelected)="optionSelected($event)" >
<mat-option *ngFor="let selectedUser of availableUsers" [ngValue]="selectedUser">
<span>{{ selectedUser?.UserName }}</span>
</mat-option>
</mat-autocomplete>
</mat-input-container>
As a demo, I also have a stackblitz with my error provided here:
https://stackblitz.com/edit/angular-5wk4rl?file=app%2Fautocomplete-simple-example.html
I am getting the error:
Template parse errors:
Can't bind to 'ngValue' since it isn't a known property of 'mat-option'.
1. If 'mat-option' is an Angular component and it has 'ngValue' input, then verify that
it is part of this module.
2. If 'mat-option' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the
'#NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the
'#NgModule.schemas' of this component.
As mentioned in other answer on stack, Angular - Can't bind to 'ngValue' since it isn't a known property of 'mat-option'
Users are suggesting that adding it to the modules file will solve the issue but when I tried that (as seen in my material-module.ts in my stackblitz), the error persists.
Any suggestions? I would appreciate any help!
<mat-option *ngFor="let option of options" [value]="option">
Check the documentation here: https://material.angular.io/components/autocomplete/overview
To use the object:
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn">
<mat-option
*ngFor="let selectedUser of availableUsers" [value]="selectedUser">
{{selectedUser.name}}
</mat-option>
</mat-autocomplete>
in xxx.ts file:
displayFn(user?): string | undefined {
return user ? user.name : undefined;
}
Related
I'm new to Angular so forgive me if I have this whole thing wrong. I'm attempting to get a created list in a dropdown and when the user selects it, it should record the information to the database.
Here is my code:
Component.html
<mat-form-field appearance="fill">
<mat-label>Retrieval Reason</mat-label>
<mat-select [formControl]="RR" required>
<mat-option>--</mat-option>
<mat-option *ngFor="let reason of reasons" [value]="reason">
{{reason.reason}}
</mat-option>
</mat-select>
<mat-error *ngIf="RR.hasError('required')">Please choose a reason</mat-error>
</mat-form-field>
<button
mat-raised-button
(click)="done()"
color="primary"
[disabled]="selection.selected.length === 0 || RR.hasError('required')"
>
Retrieve
</button>
Component.ts
retrievalReason: Reasons;
RR = new FormControl('', Validators.required);
reasons: Reasons[] = [
{reason: 'Cycle Count'},
{reason: 'Purge Request'},
{reason: 'Picking'},];
done() {
this.dialogRef.close({
carrier: this.carrier,
destination: this.selection.selected[0].dstId,
retrievalReason: this.RR.get('reasons').value,
});
}
I've looked up the Angular method to reading a value from a dropdown list and have tried different variable names, nothing's worked so far.
The only thing I see that could be wrong is that you try retrievalReason: this.RR.get('reasons').value but this is for a form to get the formcontrol.
You only have a formcontrol so just retrievalReason:this.RR.value should be enough.
Based on what it is selected on this field, I want to fill with data the Tasks field below.
<mat-form-field>
<mat-label>Position</mat-label>
<mat-select [(ngModel)]="position" (ngModelChange)="change(position)" multiple formControlName="position">
<mat-option *ngFor="let position of positionArray" [value]="position">
{{position}}
</mat-option>
</mat-select>
</mat-form-field>
This is the Tasks field:
<mat-form-field>
<mat-label>Tasks</mat-label>
<mat-select formControlName="tasks">
<mat-option *ngFor="let res of tasksItems" [value]="res">
{{res}}
</mat-option>
</mat-select>
</mat-form-field>
Typescript code is as below:
private tasksItems= [];
change(position) {
if (position == "IT") {
this.tasksItems= ["one", "two"];
}
else if (position == "Design") {
this.tasksItems= ["three", "four"];
}
else {
this.tasksItems= [];
}
Edit: This is the positionArray in ts. The values are stored in database and the change(position) method works fine. The problem is the field Tasks doesn't get the value that is stored and I am assuming it has something to do with [(ngModel)].
positionArray: string[] = ['IT', 'Design'];
Data is stored to database. But the problem is [(ngModel)] doesn't read the data (when I want to edit the field). Can someone explain to me why and how do I fix it?
You shouldn't need to use ngModel if you are already using formControlName.
I can't see the whole code but I assume you have something like [formGroup]="form" on the form element which would bind to the FormGroup in your ts file.
As long as your form.position form control is updated, it should reflect in your template.
If you are using reactive form controls try removing [(ngModel)]="position" and make sure the form control is set correctly in your ts file.
Edit
Also, try changing your template variable names. position seems to be used for different variables.
try:
<mat-option *ngFor="let pos of positionArray" [value]="pos">
{{pos}}
</mat-option>
Here is is my code HTML:
<mat-list-item class="primary-imenu-item" role="listitem">
<mat-select class="form-control" multiple formControlName="statusCode" (selectionChange)="getSelectedOptionText($event)">
<mat-option *ngFor="let list of statusList" [value]="list.id" checkboxPosition="before">
{{list.code}}
</mat-option>
</mat-select>
</mat-list-item>
TS Code:
getSelectedOptionText(event: MatSelectChange) {
let selectedData = {
code: (event.source.selected as MatOption).viewValue,
value: event.source.value
};
console.log(selectedData);
}
In that 'selectedData' I am getting the code value is undefined. I need to get code value from dropdown.
The event object has "value" array attribute which will always have one item. So, instead of (event.source.selected as MatOption).viewValue, you can do event.value[0]. Look at the screenshot for more details. Hope it helps.
I am trying to replace boostrap's combobox with material's autocomplete without refactoring much of the previous code;
This is what the html of the new material autocomplete looks like :
<input matInput placeholder="New room" aria-label="Newsroom Source" [matAutocomplete]="autoGroup" [formControl]="newsRoomCtrl" [value] = 'selectedNewsFeed.sourceName'>
<mat-autocomplete #autoGroup="matAutocomplete" (optionSelected)='onNewsRoomSelect($event.value)' >
<mat-option *ngFor="let newsroomsource of filteredNewsRoomSources | async" [value]="newsroomsource" [attr.data-row]="newsroomsource">
<span>{{ newsroomsource.sourceName }}</span> |
<small>Type: {{ newsroomsource.sourceType }}</small>
</mat-option>
</mat-autocomplete>
On '(optionSelected)' event I call the function onNewsRoomSelect(selectedNewsRoom: NewsRoomSource) by passing the selected newsroomsource as an object using event.value
This works fine ,the problem though is that the value of the input becomes an object in this case and NewsRoomSource object, and this is what I see in the input after the selection is made;
Selecting:
After selection :
Now I understand why this happens as I set [value] of the mat-input tag to an object i.e. newsroomsource, but I don't know how else I can reference the selected object if I don't do this.
As you can see in the code I tried using data-attribute but wasn't sure how exactly I can use it in this case
In this case newsRoomCtrl has the reference of the selected object try by printing this variable console.log(newsRoomCtrl);
Finally I think it is going to be like that, take a look to the object structure to be sure.
<input matInput placeholder="New room" aria-label="Newsroom Source" [matAutocomplete]="autoGroup"
[formControl]="newsRoomCtrl" [value] = 'newsRoomCtrl.value.sourceName'>
I'm new to Angular and html, so I'm looking for help. I have this code:
<mat-form-field>
<mat-select (valueChange)="changeStatus(list.name, card.name)">
<mat-option *ngFor="let i of lists"> {{i.name}} </mat-option>
</mat-select>
</mat-form-field>
What I need to do, is to pass {{i.name}} (instead of list.name) into changeStatus() function.
Basically what happens, is when I choose option in drop-box, I want to pass option I chose into function. Any ideas on how to do that? Thanks in advice
You can use onSelectionChange provided by MatSelect component and pass the $event variable.
Taken from the documentation: selectionChange: EventEmitter<MatSelectChange>
MatSelectChange has two properties:
source: MatSelect
value: any
You have to change:
<mat-select (valueChange)="changeStatus(list.name, card.name)">
To:
<mat-select (selectionChange)="onSelectionChange($event)">
And on your component.ts you can handle the event like this:
onSelectionChange($event: MatSelectChange) {
const list = $event.value; // const or let depending on your handle logic
// Your logic here
}
PS: 80% of the times simple tasks that you look for in Angular Material are straight forward. Make sure you check the API + Examples so you can learn the "Angular Way" of doing stuff.
It is the actual purpose of Angular Material "Our goal is to build a set of high-quality UI components built with Angular and TypeScript, following the Material Design spec. These components will serve as an example of how to write Angular code following best practices."
Use selectionChange event with Template reference variables for it
<mat-form-field>
<mat-select #ref (selectionChange)="changeStatus(ref.value)">
<mat-option *ngFor="let i of lists" [value]="i"> {{i.name}} > </mat-option>
</mat-select>
</mat-form-field>
Component
changeStatus(value)
{
console.log(value);
}
LIVE DEMO