Reputation: 1673
I'm having a lot of difficulty trying to use Angular Material, specifically with regards to the Selection List. I am displaying a list of objects in a Angular Material Selection List and I want to get the objects from the list of selected items.
This is what I have so far, but [value]="row"
just gives me true
when I call rows.selectedOptions.selected[0].value
:
submit(rows) {
console.log(rows);
console.log(rows.selectedOptions.selected[0].value);
console.log(rows.selectedOptions.selected[0]._getHostElement().innerText); // ugly hack, but at least it gives me the text of the option
}
<md-selection-list #rows dense>
<md-list-option *ngFor="let row of config.data" [value]="row">
{{row.title}}
</md-list-option>
</md-selection-list>
<div class="d-flex justify-content-end">
<div class="p-2">
<button md-button (click)="submit(rows)">
<span>Submit</span>
<md-icon aria-label="submit">arrow_forward</md-icon>
</button>
</div>
</div>
How can I get the actual row
from the list of selected options?
Upvotes: 3
Views: 3107
Reputation: 1679
I've had the same problem in angular 5 .I ended up using SelectionModel and bind a click event
<mat-selection-list #AnswerableBaseline>
<mat-list-option *ngFor="let a of dataSourceForAnswerable" (click)="onAnswerableBaselineListClicked(a)" checkboxPosition="before">
</mat-list-option>
</mat-selection-list>
ts file
selectionBaseline = new SelectionModel<Your Type>(true, []);
onAnswerableBaselineListClicked(row: any) {
if (!this.selectionBaseline.isSelected(row)) {
this.selectionBaseline.select(row);
}
else {
this.selectionBaseline.deselect(row);
}
}
Upvotes: 0
Reputation: 834
I've had the same problem with not being able to extract value from MdListOption. I ended up using the workaround that kind of defeats the purpose, but still:
<md-selection-list #rows dense>
<md-list-option *ngFor="let row of config.data" (click)="clickedOnRow(row)">
{{row.title}}
</md-list-option>
</md-selection-list>
and then keeping track of my selections in the clickedOnRow() in the component.
Upvotes: 0
Reputation: 1317
you could handle it with something like:
in your component.ts:
rows: Array<string> = []; //explicitly define and init property here
toggleRow(value:string){
if(this.rows.indexOf(value) !== -1){
this.rows.splice(this.rows.indexOf(value), 1);
}else{
this.rows.push(value);
}
}
submit(rows) {
console.log(rows);
}
and your component.html:
<md-selection-list #rows dense>
<md-list-option *ngFor="let row of config.data" (click)="toggleRow(row.title)">
{{row.title}}
</md-list-option>
</md-selection-list>
<div class="d-flex justify-content-end">
<div class="p-2">
<button md-button (click)="submit(rows)">
<span>Submit</span>
<md-icon aria-label="submit">arrow_forward</md-icon>
</button>
</div>
</div>
you could also use an Array<any>
or similar and .push()
the entire row
object into your rows
array (instead of just the .title
)...
Upvotes: 2
Reputation: 4071
Look at the API documentation : https://material.angular.io/components/list/api
@Output() selectChange :
Emitted when the option is selected.
so I guess using
<md-selection-list #rows dense>
<md-list-option *ngFor="let row of config.data" (selectChange)="onSelectOptionChange($event)">
{{row.title}}
</md-list-option>
</md-selection-list>
will give you the data you want in your TypeScript side :
onSelectOptionChange(value: any) {
console.log(value);
}
Not tested, but that should work. (NO IT DOESN'T)
EDIT : I've been doing some testing in a plunkr, and here are my results :
Provided Plunkr for free laughters : https://plnkr.co/edit/1G3bgJ2Twue0RH7CGmK2?p=preview
I've been using the same code you provided :
<md-selection-list #rows dense>
<md-list-option *ngFor="let row of config.data"
(selectChange)="onSelectChange($event)"
(deselected)="onDeselected($event)"
[checkboxPosition]="after"
[value]="[testValue]"
[selected]="[testValue]">
{{row.title}}
</md-list-option>
</md-selection-list>
<div class="d-flex justify-content-end">
<div class="p-2">
<button md-button (click)="submit(rows)">
<span>Submit</span>
<md-icon aria-label="submit">arrow_forward</md-icon>
</button>
</div>
</div>
And here is the TypeScript I used for my tests
export class App {
testValue: true;
config = {
data: [
{
title: 'Title1',
},
{
title: 'Title2',
},
{
title: 'Title3',
},
{
title: 'Title4',
}
]
}
constructor() {
}
onDeselected(value: any) {
console.log('deselected event => ', value);
}
onSelectChange(value: any) {
console.log('change => ', value);
}
submit(rows) {
console.log(rows.selectedOptions.selected.map(elements => {
return elements._getHostElement().innerText;
}));
}
}
And the results :
value
through an input is useless : it does set a value to the option-list-item which is not used for anything.selected
through an input is somewhat useless : It works when rendering, but here in the example I set them to true
, and if I submit instantly, I get no result (rows.selectedOptions.selected
is an empty array).selectChange
Output event doesn't work.deselected
Output event doesn't work.console.log(rows.selectedOptions.selected.map(elements => {
return elements._getHostElement().innerText;
}));
@Input() checkboxPosition : Whether the label should appear before or after the checkbox. Defaults to 'after'. No, it defaults to 'before' !
How can I get the actual
row
from the list of selected options?
Conclusion : You can't and this component is utter garbage : Do not use it...
Upvotes: 2