Communauté Angular Material 2 J'ai besoin de votre aide pour créer une mini variante comme l'exemple de conception de matériaux Google dans angular Material 2.
J'essaie de mettre en œuvre cela, mais je ne peux pas y arriver
<!-- ===================================================================== -->
<!-- SIDENAV && SIDENAV CONTAINER -->
<!-- ===================================================================== -->
<mat-sidenav-container>
<mat-sidenav
#adminNavMenu
mode="side"
opened="true"
style="min-width:50px; background: #F3F3F3;"
class="shadow_right" autosize>
<!-- MENU LEFT -->
<app-admin-menu-left></app-admin-menu-left>
</mat-sidenav>
<mat-sidenav-container>
<mat-nav-list style="min-width:60px;">
<mat-list-item *ngFor="let page of Menus">
<a routerLink="{{page.link}}" routerLinkActive="active"
[routerLinkActiveOptions]="{exact:true}" matLine>
<mat-icon class="home_icon collapse-icon vcenter" mat-list-icon>{{page.icon}}</mat-icon>
<span *ngIf="!showFiller">
{{page.name}}
</span>
</a>
</mat-list-item>
</mat-nav-list>
<button mat-icon-button (click)="showFiller = !showFiller" mat-raised-button>
<mat-icon *ngIf="!showFiller">chevron_right</mat-icon>
<mat-icon *ngIf="showFiller">chevron_left</mat-icon>
</button>
Après avoir cliqué pour afficher le mini-bar
Comme vous le voyez, il y a une marge de 250 px sur
mat-sidenav-content
mais je ne peux pas accéder à cet élément.
Toute aide pour résoudre ce problème sera utile.
Thanx
Bonne chance.
Aussi, j'ai fait un exemple de travail dans Stackblitz
<div>
<mat-sidenav-container>
<mat-sidenav #adminNavMenu mode="side" opened="true" style="min-width:60px; background: #F3F3F3;" class="shadow_right" autosize>
<!-- MENU LEFT -->
<!-- MENU LEFT -->
<app-admin-menu-left></app-admin-menu-left>
</mat-sidenav>
<!-- ================================================================= -->
<!-- ************************* MAIN CONTAINER ************************ -->
<!-- ================================================================= -->
<mat-sidenav-content [@onSideNavChange]="sideNavState">
<div class="main_container" fxLayout="column" fxLayoutGap="0px" style="height:100vh;">
<!-- =============================================================== -->
<!-- Your main content -->
<!-- =============================================================== -->
</div>
</mat-sidenav-content>
</mat-sidenav-container>
</div>
/**
* George35mk
*/
import { Component, OnInit } from '@angular/core';
import { MatSidenav } from '@angular/material';
import { trigger, state, style, transition, animate } from '@angular/animations';
import { MediatorService } from '@app-services/mediator/mediator.service';
@Component({
selector: 'app-admin-analytics',
templateUrl: './admin-analytics.component.html',
styleUrls: ['./admin-analytics.component.css'],
animations: [
trigger('onSideNavChange', [
state('close',
style({
'margin-left': '60px'
})
),
state('open',
style({
'margin-left': '250px'
})
),
transition('close => open', animate('250ms ease-in')),
transition('open => close', animate('250ms ease-in')),
]),
trigger('onPageReady', [
state('inactive',
style({
opacity: 0.4
})
),
state('active',
style({
opacity: 1
})
),
transition('inactive => active', animate('250ms ease-in')),
transition('active => inactive', animate('250ms ease-in')),
])
]
})
export class HomeComponent implements OnInit {
/**
* Get the sidenav state.
*/
sideNavState: string = this.mediator.getSideNavState;
constructor(
private mediator: MediatorService,
) { }
ngOnInit() {
// Subscribe on changes important.
this.mediator.sideNavListener.subscribe( state => {
this.sideNavState = state;
});
}
}
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
@Injectable()
export class MediatorService {
APP_VERSION: String = 'v8.3.1.36';
// default value.
// this variable track the value between sessions.
private _sideState: any = 'open';
/**
* This is the mini variant solution with animations trick.
*/
sideNavListener: any = new Subject();
get sideNavState() {
return this._sideState;
}
setSidenavState(state) {
this._sideState = state;
}
constructor() {
this.sideNavListener.subscribe( state => {
this.setSidenavState(state);
});
}
}
<div class="sidenav_menu_left"
[@onSideNavChange]="sideNavState"
style="width:100%; height: 100vh;"
fxLayout="column"
[style.overflow]="overflowState">
<p>Sidenav content left</p>
<!-- this can toggle the sidenav -->
<div fxFlex="100" (click)="toggleSideNav();" class="hoverble"></div>
</div>
import { Component, OnInit, Input } from '@angular/core';
import { MatSidenav } from '@angular/material';
import {trigger, state, style, transition, animate, keyframes, query, group} from '@angular/animations';
// Mediator: the main service, later this service is gonna have more generic use.
import { MediatorService } from '@app-services/mediator/mediator.service';
import { delay } from 'q';
@Component({
selector: 'app-admin-menu-left',
templateUrl: './admin-menu-left.component.html',
styleUrls: ['./admin-menu-left.component.css'],
animations: [
// animate sidenave
trigger('onSideNavChange', [
state('close',
style({
width: '60px'
})
),
state('open',
style({
width: '250px'
})
),
transition('close => open', animate('250ms ease-in')),
transition('open => close', animate('250ms ease-in')),
])
]
})
export class MenuLeftComponent implements OnInit {
/**
* Get the sidenav state,
*/
sideNavState: string = this.mediator.sideNavState;
overflowState: any = 'auto';
constructor(
private mediator: MediatorService
) {
}
ngOnInit() {
this.mediator.sideNavListener.subscribe( state => {
this.sideNavState = state;
});
}
/**
* On animation done.
* @param x
*/
animationEvent(x) {
this.overflowState = 'auto';
}
/**
* Toggle the sidenave state.
*
* Hides entire sidenav onclose.
*/
setSideNavState() {
this.mediator.toggle().then( snap => {
console.log(snap);
});
}
/**
* Toggle, Open or close the sidenav.
*
* Set the sidenave state on mediator.
*/
toggleSideNav() {
switch (this.sideNavState) {
case 'close':
this.sideNavState = 'open';
this.mediator.setSideNavState(this.sideNavState);
setTimeout( () => {{
this.sideNavText = this.sideNavText === 'open' ? 'close' : 'open';
this.sideNavIcon = this.sideNavIcon === 'open' ? 'close' : 'open';
this.sideNavCopyRight = this.sideNavCopyRight === 'open' ? 'close' : 'open';
}}, 200);
break;
case 'open':
this.sideNavText = this.sideNavText === 'open' ? 'close' : 'open';
this.sideNavIcon = this.sideNavIcon === 'open' ? 'close' : 'open';
this.sideNavCopyRight = this.sideNavCopyRight === 'open' ? 'close' : 'open';
setTimeout( () => {{
this.sideNavState = this.sideNavState === 'open' ? 'close' : 'open';
this.mediator.setSideNavState(this.sideNavState);
}}, 200);
break;
default:
console.log('#6644');
break;
}
this.overflowState = 'hidden';
}
}
J'ai beaucoup lutté avec cela. La solution est beaucoup plus simple alors vous pourriez penser ... presque tout dans angular peut être animé et nous pouvons résoudre ce problème avec quelques lignes de code d'animation très simple ...
dans un fichier appelé sidenav.animations.ts Vous allez créer une animation pour animer la largeur du <mat-sidenav> entre 200px et 60px
Vous allez créer une deuxième animation pour animer le <mat-sidenav-content> entre avoir une marge gauche de 201px et 61px.
./ sidenav.animations.ts
import {
animate,
state,
style,
transition,
trigger,
} from '@angular/animations';
/*
* animation: sideNaveAnimation
* trigger: 'openClose'
*
* comments: sets the width of an element to 200px when 'open' and to 60px
* when closed. Animates in between these two states over '0.3s'
*/
export const sideNavAnimation = trigger('openCloseSidenav', [
// ...
state('open', style({
width: '200px',
})),
state('closed', style({
width: '60px',
})),
transition('open <=> closed', [
animate('0.3s')
]),
]);
/*
* animation: sideNavContainerAnimation
* trigger: 'openCloseSidenavContent'
*
* comments: Sets the margin-left to 201px when "open" and 61px when "closed".
*/
export const sideNavContainerAnimation = trigger('openCloseSidenavContent', [
state('open', style({
'margin-left': '201px',
})),
state('closed', style({
'margin-left': '61px',
})),
transition('open <=> closed', [
animate('0.3s')
]),
]);
dans votre app.component.ts ...
Vous importerez les deux animations et les utiliserez dans le tableau d'animations qui vous permettra d'utiliser les déclencheurs définis dans sidenav.animations.ts ('openCloseSidenav' et 'openCloseSidenavContent') dans votre app.component.html
Vous allez créer un booléen (isOpen) pour garder une trace de l'état dans lequel se trouve le sidenav
Vous allez créer une fonction appelée toggle () qui fera basculer la variable isOpen entre true et false. Cette fonction sera appelée en appuyant sur un bouton dans app.component.html
./ app.component.ts N'oubliez pas d'importer votre MatSidenavModule, MatButtonsModule, MatIconModule, MatListModule et BrowserAnimationsModule dans votre app.module.ts en tant que bien ou vous ne pourrez pas utiliser <mat-sidenav> ou quoi que ce soit n'importe où dans votre app.component.html
import { Component } from '@angular/core';
//...
import { sideNavAnimation, sideNavContainerAnimation } from './sidenav.animations';
//...
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
animations: [sideNavAnimation, sideNavContainerAnimation]
})
export class AppComponent {
isOpen = true;
toggle() {
this.isOpen = !this.isOpen;
}
//...
}
et dans votre app.component.html ... Vous appellerez toggle () avec un bouton placé quelque part dans le sidenav.
Vous placerez le déclencheur d'animation: 'openCloseSidenav' sur le <mat-sidenav> avec un expression qui choisira lequel des deux états définis ('ouvert' ou 'fermé' comme défini dans sidenav.animations.ts) l'élément doit être dans et s'animer entre les états en fonction de l'état de la variable isOpen.
Vous placerez le déclencheur d'animation: 'openCloseSidenavContent' sur le <mat-sidenav-content> avec la même expression que ci-dessus.
./ app.component.html
<mat-sidenav-container>
<mat-sidenav [@openCloseSidenav]="isOpen ? 'open' : 'closed'" mode="side" opened role="navigation">
<mat-nav-list>
<!-- Place nav links here -->
<button type="button" aria-label="Toggle nav" mat-icon-button (click)="toggle()">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content [@openCloseSidenavContent]="isOpen ? 'open' : 'closed'">
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
Vous devrez remplir le reste vous-même, ma <mat-sidenav-list> contient des éléments comme indiqué ci-dessous.
... J'utilise la variable isOpen pour décider si le texte à côté des icônes doit être affiché ... Je vais bientôt soit ajouter des animations aux balises <mat-chip-list> pour les faire disparaître lorsque la bascule () est appelé et isOpen change ou je raccourcirai le temps d'animation à 0.0s pour qu'il se casse instantanément entre les deux états ...
... cela fonctionnera cependant tel quel même sans le * ngIf = "isOpen" dans la balise ...
<a mat-list-item (click)="signOut()">
<span class="app-nav-list-icon">
<mat-icon matListIcon class="app-nav-list-icon">
<fa-icon icon="sign-out-alt"style="color: #808DE1;"></fa-icon>
</mat-icon>
</span>
<mat-chip-list *ngIf="isOpen" style="padding-left: .5em;">
<mat-chip>Logout</mat-chip>
</mat-chip-list>
</a>
... à retenir ici, c'est que simple les animations peuvent être utilisées pour contrôler le comportement et l'apparence de chaque aspect de votre application ...
visitez https://angular.io/guide/animations pour plus de détails sur comment cela fonctionne ...
Vous devez mettre dans l'en-tête la propriété "redimensionnement automatique"
<mat-sidenav-container autosize >
avec cette propriété, le contenu s'adapte à la largeur du menu
En utilisant du code TypeScript, vous pouvez mettre à jour la largeur de la barre latérale comme ceci:
toggleSideBar(){
// console.log('toggle called');
// this.sb.toggle();
if(this.widthSideBar == this.widthSideBarExpanded){
this.widthSideBar = this.widthSideBarCollapsed;
}
else{
this.widthSideBar = this.widthSideBarExpanded;
}
// snav.toggle();
}
et le fichier html correspondant ressemblera
..
<mat-sidenav [style.width.px]="widthSideBar">..</mat-sidenav>
..
<mat-sidenav-content [style.marginLeft.px]="widthSideBar">..</mat-sidenav-content>
..
Ici, j'ai défini la largeur et la marge gauche du contenu à ajuster dynamiquement.