2

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.

6
  • 2
    can you share some code please? Commented Jun 29, 2020 at 20:24
  • Yes sure let me share in the question itself..!! Commented Jun 30, 2020 at 4:59
  • @Jeremy Lucas I have updated my question have a look and give me the best possible and easy way..!! Commented Jun 30, 2020 at 5:28
  • @kushalBaldev it would be better, if you can create a stackblitz ;) Commented Jul 3, 2020 at 12:59
  • @kushalBaldev can you upvote too the answers you approved ;) Commented Jul 3, 2020 at 14:23

3 Answers 3

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"
          >
Sign up to request clarification or add additional context in comments.

4 Comments

Hi @Eatos I appreciate your answer got some understanding but I am confused by the mat-cell code part I have multiple mat-cell like <td mat-cell *matCellDef="let element"> {{element.qid}} </td> <td mat-cell *matCellDef="let element"> {{element.questionText}} </td> So I need to highlight the entire row based on the the object given by the details view can you simplify a bit..? can you also provide the styles which you applied
Hi @Eatos I have updated my question adding the code can you view it please and suggest me over my 2 points in specific..!!
Well,in my example I needed to apply a class for the specific columns indeed, not entire row. You can freely append same markup to the mat-row if You want to do something on td level. About the class itself there is nothing special there, just opacity: 1;. To make it work You have to add to the <tr mat-row: a (click) event that will set the "selected" row (selectedRow) and "selected" index to the given (*matRowDef="let file...), apply a class on file === selectedRow, make Your modal emit events about changing < or >, increase/decrease an index You selected, set new selected row
Same situation here: github.com/PWrGitHub194238/Chemistry-Home-Office/blob/master/… (click)="openGallery(i)" opens a gallery with selected index (matRowDef="let file; columns: columnsToDisplay; let i = index"), openGallery sets selectedRow and index, (onImageChange)="onGalleryImageChange($event)" emits from the gallery upon < or >, updating the selectedRow which in turn make [class.row-action-hover]="file === selectedRow" active for diferent row.
1
  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;
  });
}
  1. 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

1 Comment

This answer is perfect for me but I just want a favour from you like can you show case on stackBitz the component interaction using a an external service I mean this we have done by the parent child component Interaction I would love to see by using external service too.!! Thanks in Advance keep this answer as it is I will need both of them. if you need I can create a seperate one for it..!! or is it okk here.
0

first : you can get with index like.
edit(index: number) {
this.row = this.yourObjectList[index];
}

second: you can get by object
edit(object: any) {
this.row = object;
}
<table class="table">
  <thead>
    <tr>
      <th scope="col">#</th>
      <th scope="col">First</th>
      <th scope="col">Last</th>
      <th scope="col">edit</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor='let oject of yourObjectList; let i=index'>
      <th scope="row">{{ i+1 }}</th>
      <td>{{ oject.firstName }}</td>
      <td>{{ oject.lastName }}</td>
      <td (click)='edit(i or object)'></td>
    </tr>
    
  </ tbody >
</table>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.