An angular-material-multilevel-menu for Angular 6? - angular6

I have tried to achieve a multilevel sidenav and I found this that meets my requirements:
angular-material-multilevel-menu
Demo - Note the accordion type
Unfortunately this is created for AngularJS (1.0?), which seems to not work in Angular 6.
My questions are:
Is there any other multilevel sidenav component for Angular 6? Have note found any similar on Google that works.
Is it possible to "upgrade" this Angular 1.0 menu to Angular 6? How?
Is there any simple instructions or courses to build your own multilevel side nav? There are many instructions for one-level, but I have found none multi-level.

I don't know if you are still looking for angular-material-multilevel-menu but I have found one made by ShankyTiwari.
Here is the link for GitHub and the link for the demo.
Very easy to use and to implement. For example, I implemented it in a sidebar because it does not exist with Angular material.
If not an alternative would be PrimeNG as #Dino said.

Angular Material 6.0 doesn't come with multilevel menu out of the box. You would have to create it on your own. It would be a combination of Nested Menu, and Side Nav.
And to answer your first question, I'd suggest you to take a look at PrimeNG's Panel Menu. It does exactly what you need and with some little effort, you'll also be able to change it's design into Material like. (I did it with some PrimeNG components, so I can confirm that it works.
Please take in consideration that PrimeNG 6.0.0 is currently in
Alpha-2 version.

I found a PART of a solution.
Here is a demo using "mat-expansion-panel"
There are still some issues that must be solved.
The shadow and offset of the Expansion Level
The shutdown instead of stay selected
Better way to do this?
Any suggestions?

I was looking to create multi-level menus with native angular material but still under development by ng material team. So, I'd like to suggest to use ng-material-multilevel-menu package for now by follow the below:
npm install --save ng-material-multilevel-menu or yarn add --save ng-material-multilevel-menu
Then import NgMaterialMultilevelMenuModule by
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
/* Import the module*/
import { NgMaterialMultilevelMenuModule } from 'ng-material-multilevel-menu';
import { AppComponent } from './app.component';
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
NgMaterialMultilevelMenuModule // Import here
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Call <ng-material-multilevel-menu [configuration]='config' [items]='appitems' (selectedItem)="selectedItem($event)"></ng-material-multilevel-menu> in your html.
Finally, declare appitems for your list items and config object
appitems = [
{
label: 'NPM',
icon: 'favorite',
link: 'https://www.npmjs.com/package/ng-material-multilevel-menu',
externalRedirect: true
},
{
label: 'Item 1 (with Font awesome icon)',
faIcon: 'fab fa-500px',
items: [
{
label: 'Item 1.1',
link: '/item-1-1',
faIcon: 'fab fa-accusoft'
},
{
label: 'Item 1.2',
faIcon: 'fab fa-accessible-icon',
items: [
{
label: 'Item 1.2.1',
link: '/item-1-2-1',
faIcon: 'fas fa-allergies'
},
{
label: 'Item 1.2.2',
faIcon: 'fas fa-ambulance',
items: [
{
label: 'Item 1.2.2.1',
link: 'item-1-2-2-1',
faIcon: 'fas fa-anchor',
onSelected: function() {
console.log('Item 1.2.2.1');
}
}
]
}
]
}
]
},
{
label: 'Item 2',
icon: 'alarm',
items: [
{
label: 'Item 2.1',
link: '/item-2-1',
icon: 'favorite'
},
{
label: 'Item 2.2',
link: '/item-2-2',
icon: 'favorite_border'
}
]
},
{
label: 'Item 3',
link: '/item-3',
icon: 'offline_pin',
onSelected: function() {
console.log('Item 3');
}
},
{
label: 'Item 4',
link: '/item-4',
icon: 'star_rate',
hidden: true
}
];
config = {
paddingAtStart: false,
classname: 'my-custom-class',
listBackgroundColor: '#fafafa',
fontColor: 'rgb(8, 54, 71)',
backgroundColor: '#fff',
selectedListFontColor: 'red',
interfaceWithRoute: true
};
Note: interfaceWithRoute will enable root item to be linkable if link property is available.

Related

TopNav Menu Navigation Example - Icon not shows on first menu

I've followed Dynamic nested topnav menu to create a navigation bar.
It was working perfectly until that I've tried to add an icon to the parents menu by change the code iconName: 'close' to iconName: 'arrow_circle_down' for DevFestFL.
The icon just cannot be displayed, but it works fine on its children.
{
displayName: 'DevFestFL',
iconName: 'arrow_circle_down',
children: [
{
displayName: 'Speakers',
iconName: 'arrow_circle_down',
children: [
{
displayName: 'Michael Prentice',
iconName: 'person',
route: 'michael-prentice',
children: [
{
displayName: 'Create Enterprise UIs',
iconName: 'star_rate',
route: 'material-design',
},
],
},
Thank you Agustin L. Lacuara
I have installed the package, and I have tried Angular Material Icons.
displayName: 'Reports',
iconName: 'arrow_downward',
children: [
{
displayName: 'Content History Report',
iconName: 'arrow_downward',
route: 'reports/content-history'
},
{
displayName: 'Drive History Report',
iconName: 'article',
route: 'reports/drive-history'
}
]
However, it only worked for child menu.
Icon is not working for parents menu
Try using icons from Angular Material Icons. Here there is a cheatsheet that might help you, it did in some projects for me.
https://jossef.github.io/material-design-icons-iconfont/
<!-- Handle branch node buttons here -->
<span *ngIf="item.children && item.children.length > 0">
<button
mat-button
[matMenuTriggerFor]="menu.childMenu"
[disabled]="item.disabled"
>
{{ item.displayName }}
<mat-icon>{{ item.iconName }} </mat-icon>
</button>
<app-menu-item #menu [items]="item.children"></app-menu-item>
</span>
One line was missed from the example.

How to bind to ngFor

I'm trying to creating an application that shows different events but when I load the webpage, it is empty and the console says 'Can't bind to 'ngForEvent' since it isn't a known property of 'div'. How do I fix that so the events are seen on the webpage?
events-list.component.ts
import { Component } from '#angular/core'
#Component({
selector: 'events-list',
template: `
<div>
<h1>Upcoming Angular Events</h1>
<hr/>
<div class="row">
<div *ngFor="Let event of events" class="col-md-5">
<event-thumbnail [event]="event"></event-thumbnail>
</div>
</div>
</div>
`
})
export class EventsListComponent {
events = [
{
id: 1,
name: 'Angular Connect',
date: '9/26/2036',
time: '10:00 am',
price: 599.99,
imageUrl: '/assets/images/angularconnect-shield.png',
location: {
address: '1057 DT',
city: 'London',
country: 'England'
},
sessions: [
{
id: 1,
name: "Using Angular 4 Pipes",
presenter: "Peter Bacon Darwin",
duration: 1,
level: "Intermediate",
abstract: `Learn all about the new pipes in Angular 4, both
how to write them, and how to get the new AI CLI to write
them for you. Given by the famous PBD, president of Angular
University (formerly Oxford University)`,
voters: ['bradgreen', 'igorminar', 'martinfowler']
}
}
}
you can use #Input decorator for this problem.
https://angular.io/guide/inputs-outputs
this link also help to solve the problem.

How to hide my left nav menu only on certain pages

I am working on a angular5/html 5 project. I have a side-nav-menu component that displays on all the pages of my app. The thing is that this side-nav-menu component is dynamic and automatically updates if any more pages are added in the app.
Now what i want to do is hide this menu only on certain pages. for example i want to remain visible on page 1-5, hidden on page 6-8 and again visible on 9 and 10. How should i do this?
This is my edited html code for side-nav-menu:
<aside>
<div class="sidebar">
<nav>
<div class="sidebar__wrap">
<ol class="left-nav">
</ol>
</div>
</nav>
</div>
</aside>
See How to get current route
You can read the route from the Router object from the parent component of the sideNav or in sideNav itself and *ngIf on the template:
constructor(router: Router) {
router.events.subscribe(event => {
if (router.url === 'SOMEROUTE') {
this.showSideNav = false;
}
}
}
then set *ngIf on your side nav to showSideNav.
Looks like a suitable case for a Shell Component. You can create one that is going to shell the whole area of your App. In this you can have a <router-outlet></router-outlet> which is going to host all the pages without the side-nav.
And for the pages that you want to have a side-nav, you can create a parent route(say /app) and then in its children define the routes for the pages that you want to have the side-nav.
So your routeConfig would look something like:
const APP_ROUTES: Routes = [
{ path: '6', component: Component6 },
{ path: '7', component: Component7 },
{ path: '8', component: Component8 },
{ path: 'app', component: ComponentApp, children: [
{ path: '1', component: Component1 },
{ path: '2', component: Component2 },
{ path: '3', component: Component3 },
{ path: '4', component: Component4 },
{ path: '5', component: Component5 },
{ path: '9', component: Component9 },
{ path: '10', component: Component10 },
]}
];
Now, in the AppComponent's template, add a <router-outlet></router-outlet>. This is supposed to load ComponentApp, Component6, Component7, and Component8. And then there would be ComponentApp that will have the side-nav and below that, another <router-outlet></router-outlet> that is going to load Component1-Component5, Component9 and Component10.
Just one thing that is going to be an issue in your case would be, you'll have to consider the children components to be under a sub-route.
Deborah Kurata has a very interesting NGCONF Talk about this and several other router related concepts that I suggest you watch to get a better understanding.

(swipeup) isn't triggering in Angular 4 with Hammerjs

I have noticed that the directive (swipeup) does not seem to be working:
I have tried using (swipeleft) and that works:
<div [#myAnimation] (swipeup)="showActionBar = false" fxFlex="56px" *ngIf="showActionBar" fxLayoutWrap fxLayoutAlign="start center"fxLayoutGap="8px" class="overview-actions">
Does anyone have a solution / work-around for this. I have looked but didn't find a solution linked to my problem.
Thank you,
J.
You can import the hammer config from #angular/platform-browser and override it. Swipe up and down are off by default as they can cause issues for the user when they are trying to scroll.
app.module.ts
import * as Hammer from 'hammerjs';
import { HammerGestureConfig, HAMMER_GESTURE_CONFIG } from '#angular/platform-browser';
export class HammerConfig extends HammerGestureConfig {
overrides = <any>{
'swipe': { direction: Hammer.DIRECTION_ALL }
};
}
#NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
{
provide: HAMMER_GESTURE_CONFIG,
useClass: HammerConfig
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
According to this can you try this?
var hammertime = new Hammer(document.body);
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
And according to the documentation
"By default it adds a set of tap, doubletap, press, horizontal pan and swipe, and the multi-touch pinch and rotate recognizers. The pinch and rotate recognizers are disabled by default because they would make the element blocking, but you can enable them by calling:
hammertime.get('pinch').set({ enable: true });
hammertime.get('rotate').set({ enable: true });
Enabling vertical or all directions for the pan and swipe recognizers:
hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammertime.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });

How to use css-modules and bootstrap at same time?

I'm using electron-react-boilerplate for my project and this boilerplate is using css-modules for styling purpose.
I'm having trouble with using bootstrap and custom style at the same place.
Suppose i've a code snippet like,
<div className="container">
<div className="row custom-css">
// other codes...
</div>
in that case 'row' is one bootstrap className and 'custom-css' is my own style className.
please help me to find some solution for these problem so that i can use css-modules and bootstrap together...
You need to import your CSS module styles from a module file specific to this component, then interpolate them into the classname via the returned object...
MyComponent.css
.myCustomClassName {
color: #fff;
}
MyComponent.js
import styles from './MyComponent.css';
<div className={`row ${styles.myCustomClassName}`} />
When output as HTML this would become something like...
<div class="row MyComponent__myCustomClassName___n1cC4ge}` />
So as long as you are loading the bootstrap CSS somewhere that should pick up on both
thanks guys i find it working by adding {} around that
<div className={`row ${styles.myCustomClassName}`} />
I was kinda stuck with this (as to how to load Bootstrap).
I created this rough edit in my webpack config file.
{
test: /(\.bootstrap\.css$|bootstrap-theme.css|bootstrap.css)/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
minimize: true || {/* CSSNano Options */}
}
},
],
},
{
test: /^((?!\.bootstrap|bootstrap-theme).)*\.css$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]',
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
}
]
},
The rest are covered perfectly by alechill