Facing issue with binding Data from JSON Object to <mat-select> - json

I am having trouble in populating the drop-down list from the JSON Response object coming from the API..
component.ts code
for (let k in keys) {
this.form.controls['id'].setValue(data[k].name);
console.log(data[k].name);
}
});
component.html code
<mat-form-field>
<mat-label>Select a User</mat-label>
<mat-select formControlName="id">
<mat-option *ngFor="let opt of options" [value]="opt.data" >
{{ opt.data.name}}
</mat-option>
</mat-select>
</mat-form-field>
console.log(data)
0: {id: 1, name: "User1"}
1: {id: 2, name: "User2"}
2: {id: 3, name: "User3"}
3: {id: 4, name: "User4"}
...
console.log(data[k].name); //This is the data I need on drop-down
User1
User2
User3
User4
...
The console.log data shows the index on every object. My JSON Object is pretty simple though.
It looks like:
[
{
"id": 1,
"name": "User1"
},
{
"id": 2,
"name": "User2"
},...
]
Kindly let me know what am I doing wrong. Thanks.
 EDIT
Here's working
Stackblitz Example

If I understand the question correctly, your API response is a list so just bind that with a for loop to Mat-Option.
HTML Code:
<mat-card>
<form [formGroup]="form" (submit)="add()">
<mat-form-field>
<mat-label>Select a User</mat-label>
<mat-select formControlName="id">
\/\/
<mat-option *ngFor="let key of users" [value]="key">
{{ key.name }}
</mat-option>
</mat-select>
</mat-form-field>
<br/>
<div fxLayout>
<div>
<button
mat-raised-button
color="accent" [disabled] = "form.invalid">Save
</button>
</div>
</div>
</form>
</mat-card>
TS Code:
getUsers(): void {
this.usersService.getUsers().subscribe(users => {
this.users = users;
console.log(this.users)
});
}
Forked_Stackblitz

Try this:
<mat-form-field>
<mat-label>Select a User</mat-label>
<mat-select formControlName="id">
<mat-option *ngFor="let item of list" [value]="item" >
{{ item.name }}
</mat-option>
</mat-select>
</mat-form-field>
Modify your TS file according to this :
list:any=[];
getUsers(): void {
this.usersService.getUsers()
.subscribe(users => {
this.users = users;
const data: User[] = this.users;
console.log('data',data)
console.log("object",Object.keys(data));
const keys: number[] = Object.keys(data) as any;
console.log("keys",keys);
console.log("users",this.users);
for (let k in keys) {
this.form.controls['id'].setValue(data[k].name);
console.log(data[k]);
this.list.push(data[k]);
}
});
}

Related

Setting value of FormControl does not trigger valueChanges

I have an Angular Material Autocomplete and I am trying to trigger the valueChanges subscription by setting a value in ngAfterViewInit. But nothing happens and I dont know why. I also checked similar questions and the answers didnt help me out so far.
This is the relevant code:
options$?: Observable<GroupOption[]>;
/** interne Liste der Optionen zum Filtern, Prüfen etc. von Items */
private options: GroupOption[] = [];
private emptyOption: OptGroupItem = {
group: '',
name: '',
id: '',
};
control = new FormControl('');
ngOnInit(): void {
this.options$ = this.control.valueChanges.pipe(
startWith(''),
map(value => this.createGroupOptions(value)),
tap(value => console.log(value))
);
this.options$.subscribe(res => {
console.log("options");
console.log(res);
})
}
ngAfterViewInit() {
console.log('what is inside field?');
console.log(this.control.value);
this.control.setValue(this.emptyOption);
}
And my html:
<mat-form-field appearance="outline">
<mat-label>{{ label }}</mat-label>
<ng-container>
<input
type="text"
matInput
[formControl]="control"
[matAutocomplete]="auto"
/>
<mat-autocomplete
#auto="matAutocomplete"
(optionSelected)="onDropdownChange($event)"
[displayWith]="displayName"
>
<mat-optgroup
*ngFor="let option of options$ | async"
[label]="option.group"
>
<mat-option *ngFor="let item of option.items" [value]="item">
{{ item.name }}
</mat-option>
</mat-optgroup>
</mat-autocomplete>
</ng-container>
</mat-form-field>
Maybe you know whats going on? Thanks for every help!

How do you set default value in mat-select within an *ngFor

I am trying to set a default value in mat-select within an *ngFor, however, accessing the element in the array from the loop is not working as wanted. Is there any similar way to this approach?
.ts file:
persons: Person[] = .. //consist of Person with name and age
.html file:
<div *ngFor="let person of persons">
{{ person.name }}
<mat-form-field>
<mat-select [(value)]="person.age">
<mat-option value="10-20">10-20</mat-option>
<mat-option value="20-30">20-30</mat-option>
</mat-select>
</mat-form-field>
</div>
To set a default value, you need to populate your array with a value assigned to each object's age property. Then mat-select [(value)] binding can set the matching value as default.
Example (Stackblitz demo):
export class AppComponent {
persons = [
{
name: 'John Smith',
age: '30-40'
},
{
name: 'Patrick Stewart',
age: '10-20'
}
,
{
name: 'Peter Parker',
age: '20-30'
}
]
}
If your array is dynamic, you can run a loop to assign a default value to each element as well.
ngOnInit() {
this.persons.forEach(item => item.age = '10-20'); // set the default age you want
}
html:
<div *ngFor="let person of persons">
{{ person.name }}
<mat-form-field>
<mat-select [(value)]="person.age">
<mat-option value="10-20">10-20</mat-option>
<mat-option value="20-30">20-30</mat-option>
<mat-option value="30-40">30-40</mat-option>
</mat-select>
</mat-form-field>
</div>
Result:

Mat Select multiple set selected value

I want to set some items in the list to be selected when I open the list.
my page:
target page:
html
<mat-form-field
appearance="fill"
color="accent"
class="w-100 ps-lg-4 ps-0"
>
<mat-label>Applicativo Di Vendita</mat-label>
<mat-select
[formControl]="applicativoDiVenditaControl"
multiple
required
(closed)="selectOnClose()"
>
<mat-select-trigger>
{{
applicativoDiVenditaControl.value
? applicativoDiVenditaControl.value[0]
: ""
}}
<span
*ngIf="applicativoDiVenditaControl.value?.length > 1"
class="additional-selection"
>
(+{{ applicativoDiVenditaControl.value.length - 1 }}
{{
applicativoDiVenditaControl.value?.length === 2
? "altro"
: "altri"
}})
</span>
</mat-select-trigger>
<mat-option *ngIf="applicativoDiVenditaList.length <= 0" disabled
>Nessun Elemento</mat-option
>
<mat-option
*ngFor="let applicativoDiVendita of applicativoDiVenditaList"
[value]="applicativoDiVendita.value"
>{{ applicativoDiVendita.value }}</mat-option
>
</mat-select>
<mat-error *ngIf="applicativoDiVenditaControl.invalid">{{
getRequiredErrorMessage()
}}</mat-error>
</mat-form-field>
TS
applicativoDiVenditaControl: FormControl;
applicativoDiVenditaList: IdValueObj[] = [];
constructor(
#Inject(MAT_DIALOG_DATA) public product: productClass,
public dialogRef: MatDialogRef<CatalogoProdottiComponent>,
private productCharService: ProductCharService,
) {
this.applicativoDiVenditaControl = new FormControl('', Validators.required);
this.getSalesApplication();
}
getSalesApplication() {
this.productCharService.getChar('sales').subscribe(
(data) => {
this.applicativoDiVenditaList = data;
},
(error) => {
console.log(error);
}
);
}
i tried with [(ngModel)] amd with [compareWith]="comparer", but dont works
i tried this StackBlitz, but dont work too
https://stackblitz.com/edit/angular6-mat-select-with-obj-default-value?file=app%2Fselect-multiple-example.html
angular version 12.2.3
On TS
export class YourForm{
selectedValue: string[]=['0','1']
yourValues= [
{value: '0', viewValue: 'Value 0'},
{value: '1', viewValue: 'Value 1'},
{value: '2', viewValue: 'Value 2'}
];
}
On HTML
<mat-form-field>
<mat-select placeholder="Your options" [(ngModel)]="selectedValue" name="values" multiple>
<mat-option *ngFor="let v of yourValues" [value]="v.value">
{{v.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>

Material angular auto complete: how to remains the mat-option in the screen after selecting an option?

I'm using the Material auto complete angular.
After i select one option in my mat-option list, my mat-options hide. I need to remain the options after select. Gif showing the problem:
My html
<div class="col-xl-6 margemColunas">
<label>Anunciaremos nas contas *</label>
<input class="form-control inputContasB2W"
#inputContasB2W
[formControl]="contasB2WControl"
[matAutocomplete]="auto"
(matChipInputTokenEnd)="add($event)">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event, i)">
<mat-option *ngFor="let contaB2W of contasFiltradas | async" [value]="contaB2W">
{{contaB2W}}
</mat-option>
</mat-autocomplete>
</div>
<div class="col-xl-6 alinhaChips">
<mat-chip-list>
<mat-chip
*ngFor="let contaB2W of produto.contasAnunciarB2W; let j = index"
[selectable]="selected"
[removable]="removable"
(removed)="removeTag(i, j)">
{{contaB2W}}
<mat-icon matChipRemove><i class="fa fa-close"></i></mat-icon>
</mat-chip>
</mat-chip-list>
</div>
My ts:
constructor(){
this.contasFiltradas = this.contasB2WControl.valueChanges.pipe(
startWith(null),
map((nomeConta: string | null) => nomeConta ? this._filter(nomeConta) : this.contasB2W.slice()));
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.contasB2W.filter(conta => conta.toLowerCase().indexOf(filterValue) === 0);
}
selected(event: MatAutocompleteSelectedEvent, index: number): void {
this.produtosConfirmadosAnuncio[index].contasAnunciarB2W.push(event.option.viewValue);
this.inputContasB2W.nativeElement.value = '';
}
}
I used workaround to blur() and then focus() again the input.
In ts:
#ViewChild('inputContasB2W') autocompleteInput: ElementRef;
selected(event: MatAutocompleteSelectedEvent) {
[..do your stuff...]
this.autocompleteInput.nativeElement.blur();
setTimeout(() => {
this.autocompleteInput.nativeElement.focus();
}, 100
);
}
If you want to preserve input text you have to save it in _filter() and set the value again before blur() like this.contasB2WControl.setValue(this.lastFilterValue);
<mat-form-field>
<input
matInput
placeholder="New fruit..."
#input
#trigger="matAutocompleteTrigger" // <-- get trigger ref
[formControl]="control"
[matAutocomplete]="auto"
/>
<mat-autocomplete
#auto="matAutocomplete"
(optionSelected)="selected($event)"
>
<mat-option
*ngFor="let option of filteredOptions | async"
[value]="option"
(click)="$event.stopPropagation(); trigger.openPanel()" // <-- use it here
>
{{ option }}
</mat-option>
</mat-autocomplete>
</mat-form-field>

How can I show a table of the data that I see on console?

I'm building an app where someone can select an option from two drop-down lists. Selecting the first shows the second and after the second the user can see some data. I can see the data at the console but I can't show them in a table at my page. Can I use something like ngx-datatable?
showInfo(value) {
let selectedPro = this.diadikasies.find(diad => diad.id == value);
this.diadikasies = selectedPro.content;
console.log(selectedPro);
}
<div *ngIf="diadikasies && diadikasies.length > 0" class="form-group">
<label for="diadikasies">
<i class="fas fa-clipboard-list" aria-hidden="true"></i> Διαθέσιμες Διαδικασίες: </label>
<select #proc
(change)="showInfo(proc.value)">
<option [ngValue]="undefined" disabled selected>Επιλέξτε Διαδικασία</option>
<option *ngFor="let diad of diadikasies" [value]="diad.id">{{ diad.title.rendered }}</option>
</select>
</div>
This is what you want.
Next time show more code.
what you have
what you want
console.log() output
On you .ts file lets assume you have this data for 2 selects
const dataForSelect_1: any = [
{name: 'option 1, value: 'val_1'},
{name: 'option 1, value: 'val_1'}
]
const dataForSelect_2: any = [
{name: 'option 1, value: 'val_1'},
{name: 'option 1, value: 'val_1'}
]
on you .html file lets say you have this code
<form [formGroup]="form">
<mat-form-field>
<mat-select placeholder="Favorite food">
<mat-option *ngFor="let option of dataForSelect_1" [value]="food.value">
{{option.value}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field [hidden]="!form.get('dataForSelect_1').value.length > 0">
<mat-select placeholder="Favorite food">
<mat-option *ngFor="let option of dataForSelect_2" [value]="food.value">
{{option.value}}
</mat-option>
</mat-select>
</mat-form-field>
</form>
<table *ngIf="data">data</table>
<div *ngIf="selectedProcess">
<h4>{{ selectedProcess.info1 }}</h4>
<h5 *ngIf="selectedProcess.info2">INFO</h5>
</div>
so simple after all...