Offset on a SelectionChange mat-select Angular - html

I have a dropdown menu and when I select a element of this dropdown I want to extract all its data.
My .ts is :
completeInputAgencyAndVersion(event: MatSelectChange) {
if (event.value > 0) {
this.service.getCodeList(event.value).subscribe(val => { this.currCodeList = val; });
if (this.currCodeList) {
this.contextScheme.schemeId = this.currCodeList.listId.toString();
this.contextScheme.schemeAgencyId = this.currCodeList.agencyId.toString();
this.contextScheme.schemeVersionId = this.currCodeList.versionId.toString();
// this.contextScheme.ctxSchemeValues = this.convertCodeListValuesIntoContextSchemeValues(this.currCodeList.codeListValues);
this._updateDataSource(this.convertCodeListValuesIntoContextSchemeValues(this.currCodeList.codeListValues));
// this.dataSource.data = this.contextScheme.ctxSchemeValues;
}
} else {
this.contextScheme.schemeId = '';
this.contextScheme.schemeAgencyId = '';
this.contextScheme.schemeVersionId = '';
this._updateDataSource([]);
}
}
And my .html is :
<mat-form-field>
<mat-select placeholder="Code List" [(ngModel)]="contextScheme.codeListId" (selectionChange)="completeInputAgencyAndVersion($event)">
<mat-option [value]="0"> None </mat-option>
<mat-option *ngFor="let codeList of codeListsFromCodeList" [(value)]="codeList.codeListId">
{{codeList?.codeListName}}
</mat-option>
</mat-select>
</mat-form-field>
Everything is working fine except that since I m using the selectionChange method of mat-select , when I chose the first value, it s not understood as a change and therefore nothing happens. Then after that when I select another element, it just get the correct information but from the last selection, basically bc of the selectionChange.
I have already posted on stack : Offset selectionChange Angular you can check for further information.
Thank you .

I'm not sure i've fully understood what you mean, but you'll get the data throught [(value)].
If you're looking for codeList, you can you just change:
[(value)]="codeList.codeListId" to [(value)]="codeList".
Like this it should pick your codeList

It was not the selectionChange it was the subscribe that were async. I had to add another async method to fix it and now it works.
Thanks !

Related

Angular Dropdown list not reading value

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.

Not mandatory option selection in Autocomplete Angular Material [duplicate]

I'm trying to implement the autocomplete component from Angular Material:
https://material.angular.io/components/autocomplete/overview
It works well for letting the user select a particular item from the suggested list but I also want to allow the user to add items not in the list.
So lets say the suggested list has the following items:
Cats
Birds
Dogs
And the user starts typing "Do" and the autocomplete shows "Dogs" as the suggested option (because I'm also filtering the list based on what they type). But then the user continues typing "Dolls" and now nothing is displayed in the autocomplete suggestions. Then the user hits enter and it gets added to the list.
Current behavior is that if what the user typed doesn't exist in the list then they are unable to add the item.
If you add an enter key listener to the input field, you can process the entered value and add it to the options if it doesn't exist. You can also dynamically add whatever the user enters to the list of filtered options as an "add new item" option, or add an "add" icon to the field (e.g. as a matSuffix). Or you can do all three:
Stackblitz
HTML
<form class="example-form">
<mat-form-field class="example-full-width">
<input matInput placeholder="Item" aria-label="Item" [matAutocomplete]="auto" [formControl]="itemCtrl" (keyup.enter)="addOption()">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="optionSelected($event.option)">
<mat-option *ngFor="let item of filteredItems | async" [value]="item">
<span>{{ item }}</span>
</mat-option>
</mat-autocomplete>
<button *ngIf="showAddButton && itemCtrl.value" matSuffix mat-button mat-icon-button (click)="addOption()"><mat-icon matTooltip='Add "{{itemCtrl.value}}"'>add</mat-icon></button>
</mat-form-field>
</form>
TS
import { Component } from '#angular/core';
import { FormControl } from '#angular/forms';
import { Observable } from 'rxjs/Observable';
import { startWith } from 'rxjs/operators/startWith';
import { map } from 'rxjs/operators/map';
/**
* #title Autocomplete with add new item option
*/
#Component({
selector: 'autocomplete-overview-example',
templateUrl: 'autocomplete-overview-example.html',
styleUrls: ['autocomplete-overview-example.css']
})
export class AutocompleteOverviewExample {
itemCtrl: FormControl;
filteredItems: Observable<any[]>;
showAddButton: boolean = false;
prompt = 'Press <enter> to add "';
items: string[] = [
'Cats',
'Birds',
'Dogs'
];
constructor() {
this.itemCtrl = new FormControl();
this.filteredItems = this.itemCtrl.valueChanges
.pipe(
startWith(''),
map(item => item ? this.filterItems(item) : this.items.slice())
);
}
filterItems(name: string) {
let results = this.items.filter(item =>
item.toLowerCase().indexOf(name.toLowerCase()) === 0);
this.showAddButton = results.length === 0;
if (this.showAddButton) {
results = [this.prompt + name + '"'];
}
return results;
}
optionSelected(option) {
if (option.value.indexOf(this.prompt) === 0) {
this.addOption();
}
}
addOption() {
let option = this.removePromptFromOption(this.itemCtrl.value);
if (!this.items.some(entry => entry === option)) {
const index = this.items.push(option) - 1;
this.itemCtrl.setValue(this.items[index]);
}
}
removePromptFromOption(option) {
if (option.startsWith(this.prompt)) {
option = option.substring(this.prompt.length, option.length -1);
}
return option;
}
}
It's weird that the user can add an item in the suggested list. The list is suggested to the user by someone who knows what to suggest. But anyway...
The user can type anything in the field and ignore the suggestions. By ignoring the suggested Dogs and typing Dolls, user can press an "Add" button which will add whatever is typed in (Dolls) to the options array.
For example, you can do it by listening to the submit event on the form:
(ngSubmit)="options.push(myControl.value); myControl.reset()"
Here's the complete demo as well.

Angular10 - [(ngModel)] and (ngModelChange) don't read the value after it's saved to db

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>

How to get drop down text in mat-select using angular 6

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.

Passing variables into function on (valueChange) (TypeScript, Angular)

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