Browse Source

feat(theme-basic): implement collapseWithMargin animation to the application layout main navigation

pull/2000/head
mehmet-erim 7 years ago
parent
commit
6fa19229bb
  1. 192
      npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html
  2. 40
      npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts

192
npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.html

@ -3,7 +3,7 @@
id="main-navbar" id="main-navbar"
style="min-height: 4rem;" style="min-height: 4rem;"
> >
<div class="container"> <div class="container ">
<a class="navbar-brand" routerLink="/"> <a class="navbar-brand" routerLink="/">
<img *ngIf="appInfo.logoUrl; else appName" [src]="appInfo.logoUrl" [alt]="appInfo.name" /> <img *ngIf="appInfo.logoUrl; else appName" [src]="appInfo.logoUrl" [alt]="appInfo.name" />
</a> </a>
@ -15,109 +15,117 @@
> >
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="main-navbar-collapse" [ngbCollapse]="isCollapsed"> <div class="navbar-collapse" id="main-navbar-collapse">
<ul class="navbar-nav mx-auto"> <ng-container *ngTemplateOutlet="!smallScreen ? navigations : null"></ng-container>
<ng-container
*ngFor="let route of visibleRoutes$ | async; trackBy: trackByFn"
[ngTemplateOutlet]="route?.children?.length ? dropdownLink : defaultLink"
[ngTemplateOutletContext]="{ $implicit: route }"
>
</ng-container>
<ng-template #defaultLink let-route> <div *ngIf="smallScreen" class="overflow-hidden" [@collapseWithMargin]="isCollapsed ? 'collapsed' : 'expanded'">
<li class="nav-item" [abpPermission]="route.requiredPolicy"> <ng-container *ngTemplateOutlet="navigations"></ng-container>
<a class="nav-link" [routerLink]="[route.url]">{{ route.name | abpLocalization }}</a> </div>
</li>
</ng-template>
<ng-template #dropdownLink let-route> <ng-template #navigations>
<li <ul class="navbar-nav mx-auto">
#navbarRootDropdown <ng-container
ngbDropdown *ngFor="let route of visibleRoutes$ | async; trackBy: trackByFn"
[abpPermission]="route.requiredPolicy" [ngTemplateOutlet]="route?.children?.length ? dropdownLink : defaultLink"
[abpVisibility]="routeContainer" [ngTemplateOutletContext]="{ $implicit: route }"
class="nav-item"
display="static"
(click)="$event.preventDefault(); $event.stopPropagation()"
> >
<a </ng-container>
ngbDropdownToggle
class="nav-link"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
href="javascript:void(0)"
>
<i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> {{ route.name | abpLocalization }}
</a>
<div #routeContainer ngbDropdownMenu class="dropdown-menu border-0 shadow-sm">
<ng-template
#forTemplate
ngFor
[ngForOf]="route.children"
[ngForTrackBy]="trackByFn"
[ngForTemplate]="childWrapper"
></ng-template>
</div>
</li>
</ng-template>
<ng-template #childWrapper let-child> <ng-template #defaultLink let-route>
<ng-template <li class="nav-item" [abpPermission]="route.requiredPolicy">
[ngTemplateOutlet]="child?.children?.length ? dropdownChild : defaultChild" <a class="nav-link" [routerLink]="[route.url]">{{ route.name | abpLocalization }}</a>
[ngTemplateOutletContext]="{ $implicit: child }" </li>
></ng-template> </ng-template>
</ng-template>
<ng-template #defaultChild let-child> <ng-template #dropdownLink let-route>
<div class="dropdown-submenu" [abpPermission]="child.requiredPolicy"> <li
<a class="dropdown-item" [routerLink]="[child.url]"> #navbarRootDropdown
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i> ngbDropdown
{{ child.name | abpLocalization }}</a [abpPermission]="route.requiredPolicy"
[abpVisibility]="routeContainer"
class="nav-item"
display="static"
(click)="$event.preventDefault(); $event.stopPropagation()"
> >
</div>
</ng-template>
<ng-template #dropdownChild let-child>
<div
[abpVisibility]="childrenContainer"
class="dropdown-submenu"
ngbDropdown
[display]="isDropdownChildDynamic ? 'dynamic' : 'static'"
placement="right-top"
[autoClose]="true"
[abpPermission]="child.requiredPolicy"
(openChange)="openChange($event, childrenContainer)"
>
<div ngbDropdownToggle [class.dropdown-toggle]="false">
<a <a
abpEllipsis="210px" ngbDropdownToggle
[abpEllipsisEnabled]="isDropdownChildDynamic" class="nav-link"
role="button" data-toggle="dropdown"
class="btn d-block text-left dropdown-toggle" aria-haspopup="true"
aria-expanded="false"
href="javascript:void(0)"
> >
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i> <i *ngIf="route.iconClass" [ngClass]="route.iconClass"></i> {{ route.name | abpLocalization }}
{{ child.name | abpLocalization }}
</a> </a>
<div #routeContainer ngbDropdownMenu class="dropdown-menu border-0 shadow-sm">
<ng-template
#forTemplate
ngFor
[ngForOf]="route.children"
[ngForTrackBy]="trackByFn"
[ngForTemplate]="childWrapper"
></ng-template>
</div>
</li>
</ng-template>
<ng-template #childWrapper let-child>
<ng-template
[ngTemplateOutlet]="child?.children?.length ? dropdownChild : defaultChild"
[ngTemplateOutletContext]="{ $implicit: child }"
></ng-template>
</ng-template>
<ng-template #defaultChild let-child>
<div class="dropdown-submenu" [abpPermission]="child.requiredPolicy">
<a class="dropdown-item" [routerLink]="[child.url]">
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i>
{{ child.name | abpLocalization }}</a
>
</div> </div>
<div #childrenContainer ngbDropdownMenu class="dropdown-menu border-0 shadow-sm"> </ng-template>
<ng-template
ngFor <ng-template #dropdownChild let-child>
[ngForOf]="child.children" <div
[ngForTrackBy]="trackByFn" [abpVisibility]="childrenContainer"
[ngForTemplate]="childWrapper" class="dropdown-submenu"
></ng-template> ngbDropdown
[display]="isDropdownChildDynamic ? 'dynamic' : 'static'"
placement="right-top"
[autoClose]="true"
[abpPermission]="child.requiredPolicy"
(openChange)="openChange($event, childrenContainer)"
>
<div ngbDropdownToggle [class.dropdown-toggle]="false">
<a
abpEllipsis="210px"
[abpEllipsisEnabled]="isDropdownChildDynamic"
role="button"
class="btn d-block text-left dropdown-toggle"
>
<i *ngIf="child.iconClass" [ngClass]="child.iconClass"></i>
{{ child.name | abpLocalization }}
</a>
</div>
<div #childrenContainer ngbDropdownMenu class="dropdown-menu border-0 shadow-sm">
<ng-template
ngFor
[ngForOf]="child.children"
[ngForTrackBy]="trackByFn"
[ngForTemplate]="childWrapper"
></ng-template>
</div>
</div> </div>
</div> </ng-template>
</ng-template> </ul>
</ul>
<ul class="navbar-nav"> <ul class="navbar-nav">
<ng-container <ng-container
*ngFor="let element of rightPartElements; trackBy: trackElementByFn" *ngFor="let element of rightPartElements; trackBy: trackElementByFn"
[ngTemplateOutlet]="element" [ngTemplateOutlet]="element"
></ng-container> ></ng-container>
</ul> </ul>
</ng-template>
</div> </div>
</div> </div>
</nav> </nav>

40
npm/ng-packs/packages/theme-basic/src/lib/components/application-layout/application-layout.component.ts

@ -1,24 +1,25 @@
import { import {
ABP, ABP,
ApplicationConfiguration, ApplicationConfiguration,
GetAppConfiguration, Config,
ConfigState, ConfigState,
eLayoutType, eLayoutType,
SetLanguage, GetAppConfiguration,
SessionState, SessionState,
SetLanguage,
takeUntilDestroy, takeUntilDestroy,
Config,
} from '@abp/ng.core'; } from '@abp/ng.core';
import { collapseWithMargin, slideFromBottom } from '@abp/ng.theme.shared';
import { import {
AfterViewInit, AfterViewInit,
Component, Component,
OnDestroy, OnDestroy,
QueryList, QueryList,
Renderer2,
TemplateRef, TemplateRef,
TrackByFunction, TrackByFunction,
ViewChild, ViewChild,
ViewChildren, ViewChildren,
Renderer2,
} from '@angular/core'; } from '@angular/core';
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'; import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap';
import { Navigate, RouterState } from '@ngxs/router-plugin'; import { Navigate, RouterState } from '@ngxs/router-plugin';
@ -31,12 +32,11 @@ import snq from 'snq';
import { AddNavigationElement } from '../../actions'; import { AddNavigationElement } from '../../actions';
import { Layout } from '../../models/layout'; import { Layout } from '../../models/layout';
import { LayoutState } from '../../states'; import { LayoutState } from '../../states';
import { slideFromBottom } from '@abp/ng.theme.shared';
@Component({ @Component({
selector: 'abp-layout-application', selector: 'abp-layout-application',
templateUrl: './application-layout.component.html', templateUrl: './application-layout.component.html',
animations: [slideFromBottom], animations: [slideFromBottom, collapseWithMargin],
}) })
export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy { export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
// required for dynamic component // required for dynamic component
@ -67,6 +67,8 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
isCollapsed = true; isCollapsed = true;
smallScreen: boolean; // do not set true or false
get appInfo(): Config.Application { get appInfo(): Config.Application {
return this.store.selectSnapshot(ConfigState.getApplicationInfo); return this.store.selectSnapshot(ConfigState.getApplicationInfo);
} }
@ -103,16 +105,22 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
constructor(private store: Store, private oauthService: OAuthService, private renderer: Renderer2) {} constructor(private store: Store, private oauthService: OAuthService, private renderer: Renderer2) {}
private checkWindowWidth() { private checkWindowWidth() {
setTimeout(() => { this.navbarRootDropdowns.forEach(item => {
this.navbarRootDropdowns.forEach(item => { item.close();
item.close(); });
}); if (window.innerWidth < 768) {
if (window.innerWidth < 768) { this.isDropdownChildDynamic = false;
this.isDropdownChildDynamic = false; if (this.smallScreen === false) {
} else { this.isCollapsed = false;
this.isDropdownChildDynamic = true; setTimeout(() => {
this.isCollapsed = true;
}, 100);
} }
}, 0); this.smallScreen = true;
} else {
this.isDropdownChildDynamic = true;
this.smallScreen = false;
}
} }
ngAfterViewInit() { ngAfterViewInit() {
@ -142,7 +150,7 @@ export class ApplicationLayoutComponent implements AfterViewInit, OnDestroy {
fromEvent(window, 'resize') fromEvent(window, 'resize')
.pipe( .pipe(
takeUntilDestroy(this), takeUntilDestroy(this),
debounceTime(250), debounceTime(150),
) )
.subscribe(() => { .subscribe(() => {
this.checkWindowWidth(); this.checkWindowWidth();

Loading…
Cancel
Save