Angular *ngFor & Materialize-CSS Collapsible Not working - html

I'm using Materialize-CSS collapsibles inside my project and I'm trying to put a collapsible inside of another.
If I remove the first *ngFor inside ng-container, then it works just fine, but once I add the *ngFor loop it will not work. Any help is appreciated! I attached the simplified code & a photo below
<ul class="collapsible" data-collapsible="expandable">
<ng-container *ngFor="let month of months">
<li >
<div class="collapsible-header">
<span><i class="material-icons">date_range</i> <strong>{{month | amDateFormat: 'MMMM YYYY'}}</strong></span>
</div>
<div class="collapsible-body">
<ul class="collapsible" data-collapsible="expandable">
<li *ngFor="let feeding of feedings | orderBy: 'date'">
<ng-container *ngIf="(month | amDateFormat: 'MMM YYYY') == (feeding.date | amDateFormat: 'MMM YYYY')">
<div class="collapsible-header valign-wrapper">
<span><i class="material-icons">today</i> <strong>{{feeding.date | amDateFormat:'MMMM Do YYYY'}}</strong></span>
</div>
<div class="collapsible-body">
...
</div>
</ng-container>
</li>
</ul>
</div>
</li>
</ng-container>
</ul>
Here is a photo showing what I want
The bottom collapsible "Month" is working correctly. The top one has the *ngFor loop and will not open the inside collapsibles
Thank you!

I was able to install angular2-materialize & hammerjs to my app and then change the ul tags
<ul class="collapsible" data-collapsible="accordion" materialize="collapsible">
I added materialize="collapsible" to both ul's and that fixed it!

Related

moving ngfor data outside of it's tag

it's my first time posting so critic for etiquette.
been using *ngFor="let item of items" in a ionic project but I ran into a problem, that being that once *ngFor is used in the a tag, I don't know who I can transfare the data for a selected item into a tag that is outside of the original tag containing it.
code:
<ion-list>
<div class="wrapper">
<ion-item-group class="day" *ngFor="let day of Excursion_Schedule" >
<ion-item-divider class="dayCard" (click)="day.displayItineraryFlag= !day.displayItineraryFlag"><ion-icon name="ios-arrow-forward" item-right></ion-icon>{{day.ExcSch_date | date:'dd'}}</ion-item-divider>
<!-- CODE I WANT TO MOVE --> <ng-container *ngIf="day.displayItineraryFlag">
<div ion-item class="cardtitle" *ngFor="let place of day.Excursion_CustomRoadMap">
<p>check</p>
<ion-item-divider class="cardtitle" *ngIf="place.Exc_CustomRoadMap_Name" (click)="place.displayStationDetailsFlag= !place.displayStationDetailsFlag">
<div class="textW">{{place.Description}} - {{place.Exc_CustomRoadMap_StartTime}}</div>
<br>
<div *ngIf="place.displayStationDetailsFlag">
<div class="mapNpic">
<img class="pics" src="{{place.Photo}}" alt="">
<img class="pics" src="https://media-cdn.tripadvisor.com/media/photo-s/14/5f/96/77/nice-view-of-the-sunset.jpg" alt="">
</div>
<div class="dits">
<br> <br>
<h3>Adress</h3>
<h3>Phone Number</h3>
<h3>Email</h3>
<h3>Website</h3>
</div>
</div>
</ion-item-divider>
</div>
</ng-container>
</ion-item-group>
</div>
<p>
TESTING 123
<!-- PLACE WHERE I WANT TO MOVE ng-container TO -->
</p>
Just use interpolation. To achieve this you have to write the selected item into a variable and then interpolate it into the outer area. Here is an example:
TS
selectedItem: any;
Excursion_Schedule: Array<any> = [];
HTML
<div><span>{{selectedItem}}</span>
<div *ngFor="let day of Excursion_Schedule">
<!-- write the selected day into the local variable here -->
</div>
</div>

click event not working in angular 8 in mobile device

A click event is not working on mobile devices. But it's working fine on other devices. If anyone knows please help to find a solution.
app.component.html:
<ul class="resp-tabs-list">
<li *ngFor="let topic of topicsList;let i=index;"(click)="getContentList(topic)" >
<i class="fa fa-book"></i> {{topic.name}}
<div *ngIf="topic.obtainMarks> 0" style="color: black">Competency level : {{topic.obtainMarks}} %
</div>
</li>
</ul>
app.component.ts:
getContentList(topic: Topics): void {
console.log(topic);
}
Try using ng-click instead of (click). I hope it will work.
<li *ngFor="let topic of topicsList;let i=index;" ng-click="getContentList(topic)">

angular7 building an navroute component but don't know what to do now

there is no issue with this code
to be more specific
can I create value's within my angular HTML or not?
I couldn't find anything about it so I think not and what do I do now if I want to create an automated menu.
i am using angular materials in this
I need to create a nav bar but I created it in angular HTML with some stuff in TS to create the data it needs to be automatic
so I need to loop this bottom part of my code with any value but I don't know how to start
<!-- need to loop this block of code whenever there is any new item with children -->
<div *ngFor="let childss of childs.children">
<div *ngIf="childss.children != null">
</div>
<a routerLink="/{{navRoute.path}}/{{childs.path}}/{{childss.path}}"><button mat-menu-item>{{childss.path}}</button></a>
</div>
</mat-menu>
</div>
<ng-template #elsesBlock>
<a routerLink="/{{navRoute.path}}/{{childs.path}}"><button mat-menu-item>{{childs.path}}</button></a>
</ng-template>
<!-- till here but have no idee how to do this effectively -->
childs is an item of an array
but it needs custom input data for the loop to function correctly but I have no idea how to do it if
<div class="nav_items" *ngFor="let navRoute of navRoutes">
<div *ngIf="navRoute.children != null; else elseBlock">
<div *ngIf="navRoute.children != null">
<a routerLink="/{{navRoute.path}}">
<button mat-button [matMenuTriggerFor]="menu">{{navRoute.path}}</button>
</a>
<mat-menu #menu="matMenu">
<div *ngFor="let childs of navRoute.children">
<div *ngIf="childs.children != null; else elsesBlock">
<a routerLink="/{{navRoute.path}}/{{childs.path}}">
<button mat-menu-item [matMenuTriggerFor]="child">{{childs.path}}</button>
</a>
<mat-menu #child="matMenu">
<!-- need to loop this blok of code when ever there is anny new item with children -->
<div *ngFor="let childss of childs.children">
<div *ngIf="childss.children != null">
</div>
<a routerLink="/{{navRoute.path}}/{{childs.path}}/{{childss.path}}"><button mat-menu-item>{{childss.path}}</button></a>
</div>
</mat-menu>
</div>
<ng-template #elsesBlock>
<a routerLink="/{{navRoute.path}}/{{childs.path}}"><button mat-menu-item>{{childs.path}}</button></a>
</ng-template>
<!-- till here but have no idee how to do this effectively -->
</div>
</mat-menu>
</div>
</div>
<ng-template #elseBlock>
<a routerLink="/{{navRoute.path}}">
<button mat-button>{{navRoute.path}}</button>
</a>
</ng-template>
</div>
this is my entire HTML
nav route is an array from my routes
I tried HTML link but that doesn't work with angular items
Try this syntax for your routerLink:
[routerLink]="['/' + navRoute.path + '/' + childs.path]"

Indirect Recursive Ng-Template in Angular 6

<ng-template #list let-Items>
<ul>
<li *ngFor="let i of Items">
<ng-container [ngTemplateOutlet]="container" [ngTemplateOutletContext]="{$implicit: i}"></ng-container>
</li>
</ul>
</ng-template>
<ng-template #container let-list>
// some code
<ng-container [ngTemplateOutlet]="list" [ngTemplateOutletContext]="
{$implicit: list.columns}"></ng-container>
</ng-template>
I have a template "container" that includes another template "item".. the container "item" includes "container" again
This is not working, I'm getting this error:
ERROR TypeError: templateRef.createEmbeddedView is not a function
Any ideas? Thanks.
This issue is quite old so you may already have found the answer but in case someone else encounter this.
The problem you had is a collision in the naming of the variable list (let-list) in your container template that overrides the list template.
If you rename the template to listTpl for example (or the variable) it should work correctly:
<ng-template #listTpl let-Items>
<ul>
<li *ngFor="let i of Items">
<ng-container [ngTemplateOutlet]="container" [ngTemplateOutletContext]="{$implicit: i}"></ng-container>
</li>
</ul>
</ng-template>
<ng-template #container let-list>
// some code
<ng-container [ngTemplateOutlet]="listTpl" [ngTemplateOutletContext]="
{$implicit: list.columns}"></ng-container>
</ng-template>
For recursion inside template, we need to understand how ng-template works along with templateOutlet in angular. If we master it the we could make the recursion easily For the reference follow following code.
<ul>
<ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: serviceNavLinks }"></ng-container>
</ul>
<ng-template #recursiveListTmpl let-list>
<li *ngFor="let item of list">
<a class="list-group-item no-border">
{{item.linkTranslationKey | translate }}
</a>
<ul *ngIf="item.childNavLinks && item.childNavLinks.length > 0">
<ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: item.childNavLinks }"></ng-container>
</ul>
</li>
This is tested in Angular 8. Did not checked for earlier versions of angular.

Creating a collapsible tree view with Angular 2

I am tring to develop my own collapsible tree view as a way to learn Angular 2. I have it partly working. Right now I am stuck on how to apply the hidden property to on the specific <li> item that has been clicked on. Here is what I have so far.
This is the html that displays the items to go in the list.
<div>
<ol>
<li *ngFor="let item of videoList">
<div>
<a *ngIf="item.nodes && item.nodes.length > 0" (click)="toggle()">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol [hidden]="!collapsed">
<li *ngFor="let subItem of item.nodes">
<a *ngIf="subItem.nodes && subItem.nodes.length > 0" (click)="toggle()">{{subItem.title}}</a>
<a *ngIf="subItem.nodes <= 0">{{subItem.title}}</a>
<ol [hidden]="!collapsed">
<li *ngFor="let video of subItem.nodes">
<a *ngIf="video.nodes && video.nodes.length > 0">{{video.title}}</a>
<a *ngIf="video.nodes <= 0">{{video.title}}</a>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</div>
and here is the typescript in the component that collapses or expands the list.
collapased = false;
toggle() {
this.collapsed = !this.collapsed;
}
currently the code collapses and expands the top level elements together and the second level elements together. I need to make each item in the list independent of the other ones. I also prefer to stay away form using CSS to achieve this.
If you add a new property in your front-end model, assuming you are using a front-end model, then you can toggle the items one at a time:
export class Item {
constructor (
public nodes: Node[],
public hidden: boolean) {}
}
<div>
<ol>
<li *ngFor="let item of videoList">
<div>
<a *ngIf="item.nodes && item.nodes.length > 0" (click)="item.hidden = !item.hidden">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol [hidden]="!item.hidden">
…
If you're not using a model like that, then the only other thing I can think of is creating a unique id tag for each by using whatever unique id comes with your data:
<a id="{{node.id}}"> </a>
Then you can hide and show based on the id property of those elements. I'm out of ideas, but I'm sure someone else will help!
I have a list of JavaScript objects "hard coded for them moment" each object has properties id: 1, title: something, collapsed: true, and nodes: [] I added the collapsed property to each node and did the following in my html.
<div>
<ol>
<li *ngFor="let item of videoList">
<div (click)="item.collapsed = !item.collapsed">
<a *ngIf="item.nodes && item.nodes.length > 0">{{item.title}}</a>
<a *ngIf="item.nodes <= 0">{{item.title}}</a>
</div>
<ol >
<li *ngFor="let subItem of item.nodes" [hidden]="item.collapsed">
<div (click)="subItem.collapsed=!subItem.collapsed">
<a *ngIf="subItem.nodes && subItem.nodes.length > 0">{{subItem.title}}</a>
<a *ngIf="subItem.nodes <= 0">{{subItem.title}}</a>
</div>
<ol>
<li *ngFor="let video of subItem.nodes" [hidden]="subItem.collapsed">
<div>
<a *ngIf="video.nodes && video.nodes.length > 0">{{video.title}}</a>
<a *ngIf="video.nodes <= 0">{{video.title}}</a>
</div>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</div>
basically what is happening is I am changing the collapsed property of the selected node.