Переключить несколько боковых навигаторов в angular 4

Моя структура компонентов

app
  --app.component.html
  --app.component.ts
  -dashboard
    --dashboard.component.html
    --dashboard.component.ts
  -sales
    --sales.component.html
    --sales.component.ts
  -taxreports
    --taxreports.component.html
    --taxreports.component.ts
  -services
    --commonservices.ts

Мой дизайн экрана

введите здесь описание изображения

Вот мой код для app.component.html

<div class="BodyStyle">
    <div class="container FirstRowContainer" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="0px">
        <div class="container FirstColumnContainer" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
            <div class="item" fxFlex="16%">
                <img class="LogoStyle" src="/src/app/Shared/Images/test.png" height="55" />
            </div>
        </div>

        <div class="container SecondColumnContainer" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
            <div class="container SecondRowContainer" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="0px">
                <div class="container" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
                    <div class="LogoHeading" fxFlex="100%">
                        <h2 class="restaurantname">Name</h2>
                    </div>
                </div>
                <div class="container" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
                    <mat-toolbar class="UserToolBarStyle">
                        <i class="material-icons UserIconStyle">
                            person
                            <button mat-button class="UserButtonStyle">
                                <h4 class="UserNameStyle">Admin</h4>
                            </button>
                        </i>
                    </mat-toolbar>
                </div>
            </div>

            <div class="container ThirdRowContainer" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="0px">
                <div class="container ThirdColumnContainer" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">

                    <div class="item" fxFlex="100%">
                        <mat-toolbar class="ToolBarStyle">
                            <button mat-button class="ButtonMenu" (click)="btnClick('dashboard');">Dashboard</button>
                            <button mat-button class="ButtonMenu" (click)="toggleSidenav('sales')">Sales</button>
                            <button mat-button class="ButtonMenu" (click)="toggleSidenav('taxreports')">Tax Reports</button>
                            <button mat-button class="ButtonMenu">MIS</button>
                            <button mat-button class="ButtonMenu">Others</button>
                        </mat-toolbar>
                    </div>
                </div>

                <div class="container FourthColumnContainer" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
                    <div class="item">
                        <mat-toolbar class="ToolBarStyle">
                            <i class="glyphicon glyphicon-log-out UserIconStyle1">
                                <button mat-button class="UserButtonStyle1">
                                    <h4 class="UserNameStyle1">Logout</h4>
                                </button>
                            </i>
                        </mat-toolbar>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="placeholder" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="0px" style="margin-top:50px;margin-left:20px;margin-right:20px;">
         <div [hidden]="salesDiv"class="item" fxFlex="100%">               
            <app-tax-reports>
                <router-outlet></router-outlet>
            </app-tax-reports>
             <app-sales>
                 <router-outlet></router-outlet>
             </app-sales> 
        </div>
        <div [hidden]="salesDiv" class="item" fxFlex="100%">
            <app-sales>
                <router-outlet></router-outlet>
            </app-sales>                           
        </div>

    </div>

    <div class="container FooterContainer" fxLayout="column" fxLayoutAlign="center" fxLayoutGap="0px">
        <div class="item item-4 FooterItem" fxFlex="100%" fxFlexOrder="2">
            <footer>
                <p class="footer_align">
                    <span class="FooterText">Powered By</span>
                    <img class="FooterImage" src="/src/app/Shared/Images/EasyResto.png" />
                </p>
            </footer>
        </div>
    </div>
</div>

Вот мой app.component.ts

import { Component, Input } from '@angular/core';
import { HttpservService } from './services/commonservice.service';
import { MatSidenav } from '@angular/material';

@Component({
    selector: 'my-app',
    templateUrl: './app.component.html',    
    providers: [HttpservService]
})
export class AppComponent {
    salesDiv: boolean;
    taxDiv: boolean;


    constructor(private sidenavService: HttpservService) {
        this.salesDiv = true;
        this.taxDiv = true;
    }

    toggleSidenav(div: string) {

        if (div == 'sales') {
            alert("sales");
            this.salesDiv = false;
            this.taxDiv = true;
            this.sidenavService.toggle();
        }
        else if (div == 'taxreports') {
            alert("taxreports");
            this.salesDiv = true;
            this.taxDiv = false;
            this.sidenavService.toggle();
        }

    }
}

Вот мой компонент продаж.html

<mat-sidenav-container>
    <mat-sidenav #sidenav mode="side" class="mat-elevation-z4">
        Sidenav
    </matmd-sidenav>
  <main>
      <ng-content></ng-content>
  </main>
</mat-sidenav-container>

Вот мой файл sales.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { HttpservService } from '../services/commonservice.service';
import { MatSidenav } from '@angular/material';
import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';

import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Component({
    selector: 'app-sales',
    templateUrl: './sales.component.html'
})
export class SalesComponent implements OnInit {   


    @ViewChild('sidenav') public sidenav: MatSidenav;

    constructor(private httpservice: HttpservService, private router: Router) {       
    }

    ngOnInit() {
        console.log(this.sidenav);
        this.httpservice.setSidenav(this.sidenav);
    }

}

В commonservice.ts я назвал toggle и sidesetnav следующим образом

 public setSidenav(sidenav: MatSidenav) {
    this.sidenav = sidenav;
}

 public toggle(isOpen?: boolean): Promise<MatDrawerToggleResult> {

    return this.sidenav.toggle(isOpen);
}

Когда я нажимаю на меню продаж, боковая навигация отлично переключается. Но когда я нажимаю меню налоговых отчетов, боковая навигация не переключается. Он просто показывает пустую страницу в области содержимого. Я не смог найти, какая боковая панель передается службе во время выполнения. Я вызываю setSidenav() как в отчетах о продажах, так и в налоговых отчетах oninit(). Итак, что происходит, так это то, что последняя пройденная боковая панель устанавливается на sidenav, и переключается только она. Я не понимаю, какую ошибку я делаю. Я даже пытался создать 2 отдельные функции, такие как setSideNav1() и toggle1(), но все равно та же проблема.

Правка: @Llorenc Pujol Ferriol: я внес несколько изменений в ваш код. Это то, что я сделал, и это работает отлично.

   <div class="placeholder" fxLayout="row" fxLayoutAlign="center" fxLayoutGap="0px" style="margin-top:50px;margin-left:20px;margin-right:20px;">
    <div fxFlex="100%">
        <router-outlet></router-outlet>
    </div>
    <mat-sidenav-container>
        <mat-sidenav #sidenav align="end" mode="side" class="mat-elevation-z4 side-nav-overflow-hidden">
            <app-sales *ngIf="salesDiv">
            </app-sales>
        </mat-sidenav>
    </mat-sidenav-container>

    <mat-sidenav-container>
        <mat-sidenav #taxnav mode="side" align="end" class="mat-elevation-z4">
            <app-tax-reports *ngIf="taxDiv">
            </app-tax-reports>
        </mat-sidenav>
    </mat-sidenav-container>
</div>

Но проблема в том, что контейнер занимает большую часть ширины, и я не могу установить ширину для контейнера matside-nav. Когда я устанавливаю, он ведет себя странно. Вот снимок экрана.

Панель инструментов и боковая панель

Обновление: я исправил проблему ширины, добавив [ngStyle]="{ 'width.vw': setSalesWidth }"


person user7906966    schedule 06.11.2017    source источник
comment
Можете ли вы показать свою налоговую составляющую? у него тоже есть сиденав?   -  person Llorenç Pujol Ferriol    schedule 06.11.2017
comment
Да, он также имеет боковую навигацию, как компонент продаж. Когда я нажимаю «Налоговые отчеты», подменю налоговых отчетов будут отображаться в виде боковой навигации.   -  person user7906966    schedule 07.11.2017


Ответы (1)


Я вижу здесь две проблемы. Первая проблема заключается в том, что условие для отображения ваших компонентов не отличается друг от друга, оба скрыты, когда salesDiv имеет значение true:

    <div [hidden]="salesDiv"class="item" fxFlex="100%">               
        <app-tax-reports>
            <router-outlet></router-outlet>
        </app-tax-reports>
         <app-sales>
             <router-outlet></router-outlet>
         </app-sales> 
    </div>
    <div [hidden]="salesDiv" class="item" fxFlex="100%">
        <app-sales>
            <router-outlet></router-outlet>
        </app-sales>                           
    </div>

Во-вторых, и САМОЕ ВАЖНОЕ, это то, что архитектура компонентов, которую вы сделали здесь, не является ожидаемой. Компонент Material2 sidenav не желательно уничтожать и инициализировать снова. Он имеет относительную анимацию и текущее состояние, что не является хорошей практикой, хотя нет причин его уничтожать, просто замените его содержимое:

<mat-sidenav-container>
    <mat-sidenav #sidenav mode="side" class="mat-elevation-z4">
       <app-sales-sidenav *ngIf="salesDiv"></app-sales-sidenav>
       <app-taxes-sidenav *ngIf="taxDiv"></app-taxes-sidenav>
    </mat-sidenav>
    <app-sales *ngIf="salesDiv"></app-sales>
    <app-taxes *ngIf="taxDiv"></app-taxes>
</mat-sidenav-container>

Эта реализация выполняется с помощью *ngIf, также может быть выполнено динамическое создание компонента. Что-то вроде этого: Динамическое создание компонента angular2 с ng-content

Это усложнит взаимодействие между компонентами, потому что оно разделено, но конечный результат будет намного лучше, а также поможет отделить ваше приложение.

Надеюсь это поможет.

person Llorenç Pujol Ferriol    schedule 07.11.2017
comment
Большое спасибо. Он работает отлично, и я немного изменил его. Обновил свой комментарий скриншотом. У меня проблема с установкой ширины. - person user7906966; 08.11.2017
comment
Привет @ user7906966, я вижу ваше решение, но, как я уже сказал, я рекомендую вам использовать только ОДИН sidenav-контейнер и ОДИН sidenav и изменять только его содержимое, как я сказал в своем ответе. Хотя, если это помогло вам решить вашу проблему, сделайте этот ответ решением. - person Llorenç Pujol Ferriol; 08.11.2017