mat-list in angular 5 - html

I have a question about implement mat-list in angular 5.
I had this code, when I had the divider insede the mat-list-item but the divider line didn't show always
<mat-list >
<mat-list-item class="pathitem" *ngFor="let item of Lst" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
<mat-divider class="background-divider"></mat-divider>
</mat-list-item>
</mat-list>
then I change that for this:
<mat-list *ngFor="let item of LstTramosFiltro" >
<mat-list-item class="pathitem" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
</mat-list-item>
<mat-divider class="background-divider"></mat-divider>
</mat-list>
My question is which of the two is the correct solution if you use ngfor in mat-list or use in mat-list-item; and where the use of the mat-divider is correct
thanks for your help.

First, ngfor should be placed in the mat-list-item instead of mat-list, otherwise you will get multiple list and each have multiple mat-list-item, and if you have multiple sections you can use mat-divider to divide into different sections, the mat-divider should be placed between two mat-list-item not inside the mat-list-item. Check https://material.angular.io/components/list/overview#lists-with-multiple-sections for details.

the first one is current. The item you need to iterate over is the one that should have ngFor. If you want to include the divider, you may wrap both items into ng-template like this:
<mat-list>
<ng-template *ngFor="let item of LstTramosFiltro">
<mat-list-item class="pathitem" style="height: 76px;">
<div>
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
</div>
</mat-list-item>
<mat-divider class="background-divider"></mat-divider>
</ng-template>
</mat-list>

You should use the ngFor for the mat-list-item, not mat-list, assuming you only want to display a single list of items.
Doc references: https://material.angular.io/components/list/examples, https://material.angular.io/components/divider/overview
If you want the divider to show after every item except the last, it can be inserted as part of the mat-list-item (which I think you did), like so:
<mat-list>
<mat-list-item class="pathitem" *ngFor="let item of Lst; last as last" style="height: 76px;">
<h3>item.title</h3>
<p>item.desc</p>
<p>item.ad</p>
<mat-divider class="background-divider" *ngIf="!last"></mat-divider>
</mat-list-item>
</mat-list>

Related

How can I convert input text on HTML to individual box-like structures each time user types a word separated by comma (see picture)

I would like to know how I can convert text data into individual boxes as shown in the picture each time user enters a word separated after a comma (I am currently creating this as an input field on Angular)
You can simply use a variable with ngModel and a *ngFor over this variable.split(',')
<input [(ngModel)]="name">
<ng-container *ngIf="name">
<div *ngFor="let item of name.split(',')">
{{item}}
</div>
</ng-container>
NOTE: You can use mat-chip-list in the way
<mat-chip-list *ngIf="name">
<mat-chip
*ngFor="let item of name.split(',');let i=index">
{{ item }}
<button matChipRemove>
<mat-icon (click)="remove(i)">cancel</mat-icon>
</button>
</mat-chip>
</mat-chip-list>
where
remove(index:number)
{
const list=this.name.split(",") //get the list
list.splice(index,1) //remove the element at position "index"
this.name=list.length?list.join(','):null //give value to name using join
}
stackblitz
NOTE: If you only need the "list" based in a variable just give value to the variable
Looks like you are looking for something like Angular Material Chips.
https://material.angular.io/components/chips/examples

ngFor custom index increment Angular

How can I use custom index increment or decrement in ngFor?
I want something like this:
`<div *ngFor="let item of items; let i = index">
<span>
{{items[i].name}}
</span>
<span>
{{items[i+1].name}}
</span>
<!-- Then I want to increment index value like i++ -->
</div>`
I mean how can I use custom for loop in angular's component html file?
I guess what you want to achieve is something like:
<div>
<span *ngFor="let item of items">
{{item.name}}
</span>
</div>
This way you don't have to increment anything - angular ngFor directive does it for you
Update I'm not sure what do you want to achieve - maybe try to describe it in a better way. Maybe try this:
<div>
<p *ngFor="let item of items; let i = index">
<span>{{item.name}}</span>
<span>{{items[i + 1].name}}</span>
</p>
</div>

How to force overflow-ed element to start at top

I have a <mat-drawer-container> that contains a <mat-selection-list>. Whenever the <mat-selection-list> has enough elements to overflow, the scrolling is not starting at the top when the elements are rendered. It's starting at the first element in the list, which hides the title and subtitle. Is there a way to force the scroll to start and the top?
[edit] I'm aware that I could leverage something like a scrollTo(), but it seems hack-y, and I'm trying to determine the best-practice approach for this.
<mat-drawer-container class="container">
<mat-drawer #drawer (openedChange)="onOpenedChange($event)" class="sidenav" mode="push" opened>
<p class="drawer-title">Data Validation</p>
<p class="drawer-subtitle">{{integrationName}}</p>
<mat-selection-list [multiple]="false">
<mat-list-option (click)="getTableNames(date)" (click)="drawer.toggle()" class="date-item" *ngFor="let date of dataServiceDates">
{{date}}
<mat-divider></mat-divider>
</mat-list-option>
</mat-selection-list>
</mat-drawer>
</mat-drawer-container>
<mat-selection-list> kind of pseudo-selects the first item in the collection of <mat-list-option>'s. This can be disabled by defaulting all of [selected] Input()'s to false
The fix was put in place like so:
<mat-drawer-container class="container">
<mat-drawer #drawer (openedChange)="onOpenedChange($event)" class="sidenav" mode="push" opened>
<p class="drawer-title">Data Validation</p>
<p class="drawer-subtitle">{{integrationName}}</p>
<mat-selection-list [multiple]="false">
<!--here--> <mat-list-option [selected]="false" (click)="getTableNames(date)" (click)="drawer.toggle()" class="date-item" *ngFor="let date of dataServiceDates">
{{date}}
<mat-divider></mat-divider>
</mat-list-option>
</mat-selection-list>
</mat-drawer>
</mat-drawer-container>

Reference ngFor value in component

I have a nested ngFor statement. I need to retrieve the value of my first ngFor on button click.
I have tried the following:
use template reference variable
use attribute binding
use Input decorator
This is my code:
<mat-expansion-panel *ngFor="let item of Datasource;">
<mat-expansion-panel-header style="display:flex" class="mat-row">
{{item.Header}}
</mat-expansion-panel-header>
<mat-selection-list [(ngModel)]="selectedOptions">
<mat-list-option *ngFor="let line of item.match; let i= index;" [value]="line">
<div class="container-name">
<div class="col-6">{{i}} - {line.user.Name }} vs {{ line.user.Address }}</div>
</mat-list-option>
</mat-selection-list>
<div style="text-align:center; padding: 20px">
<button mat-raised-button color="primary" (click)="submit()" type="submit">Add</button>
</div>
</mat-expansion-panel>
Can this be achieved?
Well, you need to clone that object properties first. As that object is linked to the template, when you manipulate it, it is manipulated on template too. You can use var obj = Object.assign({}, actual obj) and then do the manipulation on obj instead of actual one. Then it will not get affected in template. Hope it helps.

Angular4+ show/hide child element in HTML template

I am trying to implement a simple "hover on a comment to show a reply button" implementation in my angular application. Is there a way to achieve this effect by using template reference variables only?
Something along the lines of...
<mat-list>
<mat-list-item *ngFor="let comment of comments" #SomeRefToThisParticularElement (mouseenter)="SomeRefToThisParticularElement=true" (mouseleave)="SomeRefToThisParticularElement=false">
<h4>{{comment.text}}</h4>
<p> 3 replies </p>
<mat-icon *ngIf="SomeRefToThisParticularElement==true">reply</mat-icon>
</mat-list-item>
</mat-list>
Obviously, the above doesn't work cause angular won't let you assign or set template variables the way I have shown in the snippet above. But I would like to explore options to achieve this at the html template level.
Is this a good approach to do this?
Edit
Click here for a summary of possible solutions.
try this, Hide and show based on the hover index of an array.
<mat-list>
<mat-list-item *ngFor="let comment of comments; let i = index" (mouseenter)="commentIndex= i" (mouseleave)="commentIndex = -1">
<h4 mat-line>{{comment.text}}</h4>
<p mat-line style="font-size:x-small; color:rgba(0, 0, 0, 0.54)"> 3 replies </p>
<mat-icon *ngIf="commentIndex == i">reply</mat-icon>
</mat-list-item>
</mat-list>
Use a dynamic object to do this, like comment.isVisible. Now the isVisible object is dynamically created and it will be modify the value while hover in/out.
Please try this way
<mat-list>
<mat-list-item *ngFor="let comment of comments" (mouseenter)="comment.isVisible = true" (mouseleave)="comment.isVisible= false" >
<h4 mat-line >{{comment.text}}</h4>
<p mat-line style="font-size:x-small; color:rgba(0, 0, 0, 0.54)"> 3 replies </p>
<mat-icon *ngIf="comment.isVisible">reply</mat-icon>
</mat-list-item>
</mat-list>
Simplest Solution (Credit: Rahul Sharma) - use index of the element and set that as the value of a dynamic variable that is used within an *ngIf statement for show/hide behavior of an element.
Next Best Solution (Credit: Ramesh Rajendran) - Add a dynamic property to the iterable object. This assumes that the iterable object is not immutable.
Thanks to the respective contributors. Hope this helps someone in the future.
you can use css:
mat-icon{
color: transparent;
}
mat-icon:hover, mat-icon:active{
color:black;
}