问题
Hello folks I have one scenario in which I am really confused on how to figure out...!!
The scenario is I have
1)The mat table(that is the angular material table)
2)And a details view which shows the details based on the click of the particular row of the table.
3)list of objects as a data source..!!
I pass the object on the click event of the row and the object passes to the detail view and the details of that particular row is shown now the question is....!!
I have the same data source that is list of objects for details view in that I have two buttons like > < the forward and backward respectively based on the click I select the elements from the list baaed on index and show in the details view.
So according to the details view I need to select the particular row in my table..!! As the details view updates need to update the selection of the row.
So how can I achieve that?
Here goes my code
export class Question {
private questionText: String;
private qid: String;
private category: String;
private author: String;
private level: String;
constructor(qid:String,category:String,author:String,level:String,questionText:String){
this.qid=qid;
this.category=category;
this.author=author;
this.level=level;
this.questionText=questionText;
}
/**
* getQuestionText
*/
public getQuestionText() {
return this.questionText;
}
/**
* getQuestionText
*/
public getqid() {
return this.qid;
}
/**
* getQuestionText
*/
public getcategory() {
return this.category;
}
/**
* getQuestionText
*/
public getauthor() {
return this.author;
}
/**
* getlevel
*/
public getlevel() {
return this.level;
}
}
The above is the model class
public questions:Array<Question> = [
new Question("1","TEXT_FREE","Harry","1","Write an essay on Lion"),
new Question("2","TEXT_SC","Harry Potter","2","Write an essay on tiger"),
new Question("3","TEXT_MC","Harry Motter","3","Write an essay on cheetah"),
new Question("4","TEXT_BC","Harry Bobber","4","Write an essay on Leapord"),
];
above is my array of objects
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!-- QID Column -->
<ng-container matColumnDef="qid">
<th mat-header-cell *matHeaderCellDef> QID </th>
<td mat-cell *matCellDef="let element"> {{element.qid}} </td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="questionText">
<th mat-header-cell *matHeaderCellDef> Question Text </th>
<td mat-cell *matCellDef="let element"> {{element.questionText}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
the above is my mat table
most imp things that hinders me
1)Apply a class on the row when clicked like if I click the second row only that row must be highlighted..!!
2)Need to select the row of the table when the index or say the whole object passed from the details view.
回答1:
- To apply class on row, we should know that respective question is selected. So, we need to have extra property on the
Question
, which tells whether question is selected or not. Based on that we can add or remove the class on row using[ngClass]={ 'class-name' : <condition> }
export class Question { public questionText: string; public qid: string; public category: string; public author: string; public level: string; public selected ? : boolean = false; constructor(question: Question) { Object.assign(this, question); } }
And in the template file
<tr mat-row
*matRowDef="let row; columns: displayedColumns;"
(click)="getQuestion(row)"
[ngClass]="{ 'selected-row' : row.selected }"
></tr>
And logic to select the row
public getQuestion(question: Question) {
this.removeSelection();
this.selectedQuestion = question;
this.selectedQuestion.selected = true;
}
private removeSelection() {
this.questions.map((question: Question) => {
return question.selected = false;
});
}
- In the details view, you need to have event emitter which emits question index to select it in table
export class HelloComponent { @Input() question: Question; @Output() changeQuestion: EventEmitter < number > = new EventEmitter < number > (); public previousQuestion() { let index = +this.question.qid; index -= 1; this.changeQuestion.emit(index); } public nextQuestion() { let index = +this.question.qid; index += 1; this.changeQuestion.emit(index); } }
You can find the working stackblitz from here
回答2:
As You are using MatTable and in row definiotion You are using probably something like <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
, I would say You can try adding an index and use it to open dialog - pass datasource object with the index and based on it You can optionaly even report back to the MatTable that You have decreased or increased the second one.
Like <mat-row *matRowDef="let row; let i = index; columns: displayedColumns;" (click)="openSelected(datasource, i)"></mat-row>
And "selection" is just a trick to see if the let i = index
is equal to the index given by You, nothing more. I imagine (click)="openSelected(datasource, i)
will set some values to the bindings for the details view, show it and arrows in that view will emit events so in the main component You can set 'selectedIndex' field as You like.
You can take a look at my app's example code here. I've used the image gallery there and on image change I'm also changing the underlying "selected" row. It is probably what You want to do more or less.
onGalleryImageChange(index: number) {
this.selectedFileForGallery = this.data[index];
this.selectedRow = this.selectedFileForGallery;
}
and in the view:
<tr
mat-row
fxLayout="column"
fxLayoutAlign="center"
*matRowDef="let file; columns: columnsToDisplay; let i = index"
matTooltipClass="multiline-tooltip"
[matTooltip]="getFileTooltip(file)"
(mouseenter)="mouseEnter(file)"
(mouseleave)="mouseLeave()"
(click)="openGallery(i)"
></tr>
</table>
And
<td mat-cell *matCellDef="let file">
<div
fxLayout="row"
fxLayoutAlign="space-between center"
class="row-action"
[class.row-action-hover]="file === selectedRow"
>
来源:https://stackoverflow.com/questions/62646083/how-to-select-the-table-row-in-angular-based-on-the-object