将孩子作为孩子的父母-路由器,面包屑,导航

时间:2019-04-26 10:08:30

标签: angular angular2-routing

因此,我有一个由面包屑导航选项功能

组成的应用程序
  • 带有基本选项的登机屏幕,这些选项卡可以是可变的,即不固定为3 enter image description here

  • 用户选择了选项1的第一级屏幕,查看面包屑的变化方式,这些选项卡可以是可变的,即不固定为3 enter image description here

    • 二级屏幕,用户在其中选择了选项A,并在此处查看面包屑的变化,这些选项卡可以是可变的,即不固定为3

enter image description here

  

在上图中,“面包屑”和“选项”清晰可见,但是只要没有其他选项或子选项,功能组件就会加载或替换选项容器区域。

我的应用程序的目录结构如下,

enter image description here

下面的“操作和导航”文件夹包含以下文件,

enter image description here

下面是我编写的代码,

core.module.ts

import { NgModule } from '@angular/core';
import { FooterComponent } from './footer/footer.component';
import { HeaderComponent } from './header/header.component';
import { NavigationComponent } from './navigation/navigation.component';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PMRoutingModule } from '../router/pmrouter.module';
import { MatPaginatorModule,
  MatSortModule,
  MatTableModule,
  MatFormFieldModule,
  MatInputModule,
  MatCheckboxModule,
  MatButtonModule,
  MatProgressSpinnerModule,
  MatOptionModule,
  MatSelectModule,
  MatDialogModule,
  MatAutocompleteModule,
  MatRadioModule,
  MatSnackBarModule,
  MatDatepickerModule,
  MatNativeDateModule} from '@angular/material';
import { ActionsListComponent } from './actions/actions-list.component';
import { ActionThumbnailComponent } from './actions/action-thumbnail.component';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    BrowserAnimationsModule,
    MatPaginatorModule,
    MatSortModule,
    MatTableModule,
    MatFormFieldModule,
    MatInputModule,
    MatCheckboxModule,
    MatButtonModule,
    MatProgressSpinnerModule,
    MatOptionModule,
    MatSelectModule,
    ReactiveFormsModule,
    MatDialogModule,
    MatAutocompleteModule,
    MatRadioModule,
    MatSnackBarModule,
    MatDatepickerModule,
    MatDatepickerModule,
    MatNativeDateModule,
    PMRoutingModule
  ],
  declarations: [
    HeaderComponent,
    FooterComponent,
    NavigationComponent,
    ActionsListComponent,
    ActionThumbnailComponent
  ],
  exports: [
    HeaderComponent,
    FooterComponent,
    NavigationComponent,
    CommonModule,
    FormsModule,
    BrowserAnimationsModule,
    MatPaginatorModule,
    MatSortModule,
    MatTableModule,
    MatFormFieldModule,
    MatInputModule,
    MatCheckboxModule,
    MatButtonModule,
    MatProgressSpinnerModule,
    MatOptionModule,
    MatSelectModule,
    ReactiveFormsModule,
    MatDialogModule,
    MatAutocompleteModule,
    MatRadioModule,
    MatSnackBarModule,
    MatDatepickerModule,
    MatDatepickerModule,
    MatNativeDateModule,
    PMRoutingModule
  ]
})
export class CoreModule { }

navigation.component.ts

import { Component, OnInit } from '@angular/core';
import { Params, ActivatedRoute, Router, NavigationEnd, PRIMARY_OUTLET } from '@angular/router';
import { filter } from 'rxjs/operators';

interface IBreadcrumb {
  label: string;
  params: Params;
  url: string;
}

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements OnInit {

  public breadcrumbs: IBreadcrumb[];

  /**
   * @class DetailComponent
   * @constructor
   */
  constructor(
    private activatedRoute: ActivatedRoute,
    private router: Router
  ) {
    this.breadcrumbs = [];
  }

  /**
   * Let's go!
   *
   * @class DetailComponent
   * @method ngOnInit
   */
  ngOnInit() {
    const ROUTE_DATA_BREADCRUMB: string = "breadcrumb";

    //subscribe to the NavigationEnd event
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd))
      .subscribe(event => {
      //set breadcrumbs
      let root: ActivatedRoute = this.activatedRoute.root;
      this.breadcrumbs = this.getBreadcrumbs(root);
    });
  }

  /**
   * Returns array of IBreadcrumb objects that represent the breadcrumb
   *
   * @class DetailComponent
   * @method getBreadcrumbs
   * @param {ActivateRoute} route
   * @param {string} url
   * @param {IBreadcrumb[]} breadcrumbs
   */
  private getBreadcrumbs(route: ActivatedRoute, url: string='', breadcrumbs: IBreadcrumb[]=[]): IBreadcrumb[] {
    const ROUTE_DATA_BREADCRUMB: string = "breadcrumb";

    //get the child routes
    let children: ActivatedRoute[] = route.children;

    //return if there are no more children
    if (children.length === 0) {
      return breadcrumbs;
    }

    //iterate over each children
    for (let child of children) {

      console.log(child.url);

      //verify primary route
      if (child.outlet !== PRIMARY_OUTLET) {
        continue;
      }

      //verify the custom data property "breadcrumb" is specified on the route
      if (!child.snapshot.data.hasOwnProperty(ROUTE_DATA_BREADCRUMB)) {
        return this.getBreadcrumbs(child, url, breadcrumbs);
      }

      //get the route's URL segment
      let routeURL: string = child.snapshot.url.map(segment => segment.path).join("/");

      //append route URL to URL
      url += `/${routeURL}`;

      //add breadcrumb
      let breadcrumb: IBreadcrumb = {
        label: child.snapshot.data[ROUTE_DATA_BREADCRUMB],
        params: child.snapshot.params,
        url: url
      };
      breadcrumbs.push(breadcrumb);

      //recursive
      return this.getBreadcrumbs(child, url, breadcrumbs);
    }
  }


}

navigation.component.html

<nav class="spacing">
  <ol class="cd-breadcrumb triangle custom-icons">
    <li *ngFor="let breadcrumb of breadcrumbs; let i = index" [ngClass]="breadcrumbs.length === (i + 1) ? 'current' : ''">
      <div *ngIf="breadcrumbs.length === (i + 1);then last else parent"></div>
      <ng-template #last>
          <em>{{ breadcrumb.label }}</em>
      </ng-template>
      <ng-template #parent>
          <a [routerLink]="breadcrumb.url">{{ breadcrumb.label }}</a>
      </ng-template>
    </li>
  </ol>
</nav>

actions-list.component.ts

import { Component, OnInit } from '@angular/core';
import { Route, Router, NavigationEnd, ActivatedRoute, UrlSegment } from '@angular/router';
import { filter } from 'rxjs/operators';

@Component({

  templateUrl: './actions-list.component.html',
  styleUrls: ['./actions-list.component.css']
})
export class ActionsListComponent implements OnInit {

  rowActionClass: string[] = ['col-md-3 col-lg-2 col-sm-4 col-xs-6 card-short', 'col-md-3 col-lg-3 col-sm-4 col-xs-6 card-long'];

  allRoutes = [] as Imenuoption[];
  actions = [] as Imenuoption[];
  errorMessage: string;
  event = {} as NavigationEnd;

  constructor(private router: Router) {

    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd))
      .subscribe(event => {
        this.allRoutes = [];
        this.getAllRoutes('', this.router.config);
        this.setupActions();
    });
  }

  ngOnInit(): void {
  }

  setupActions() {

    this.actions = [];
    const currentRoute: string[] = this.router.url.split('/');

    for (let i = 0; i < this.allRoutes.length; i++) {
      const str = this.allRoutes[i];
      const rData: string[] = str.navURL.split('/');
        if (this.router.url !== '/' && currentRoute.length === rData.length - 1 ) {
          this.actions.push(this.allRoutes[i]);
        }
    }
  }

  getAllRoutes(parent: String, config: Route[]): Imenuoption[] {
    for (let i = 0; i < config.length; i++) {
      const route = config[i];

      const option = {} as Imenuoption;
      option.navURL = parent + '/' + route.path;
      option.imageURL = option.navURL === '/' ? '' : route.data.imageURL;
      option.description = option.navURL === '/' ? '' : route.data.breadcrumb;

      this.allRoutes.push(option);

      if (route.children) {
        const currentPath = route.path ? parent + '/' + route.path : parent;
        this.getAllRoutes(currentPath, route.children);
      }
    }
    return this.allRoutes;
  }

}

actions-list.component.html

<div class="row">
  <div class="col-md-10 col-lg-10 col-md-offset-1 col-lg-offset-1">
    <div class="row">
      <ng-template ngFor let-actionCard="$implicit" [ngForOf]="actions">
        <div [ngClass]="actions.length > 4 ? rowActionClass[0] : rowActionClass[1]">
          <div *ngIf="actions.length > 4 ;then small else large"></div>
          <ng-template #small>
            <app-action-thumbnail [action]="actionCard" [cssCardHeight]="0"></app-action-thumbnail>
          </ng-template>
          <ng-template #large>
            <app-action-thumbnail [action]="actionCard" [cssCardHeight]="1"></app-action-thumbnail>
          </ng-template>
        </div>
      </ng-template>
    </div>
  </div>
</div>

action-thumbnail.component.ts

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-action-thumbnail',
  templateUrl: './action-thumbnail.component.html',
  styleUrls: ['./action-thumbnail.component.css']
})
export class ActionThumbnailComponent implements OnInit {
  @Input() action: Imenuoption;

  @Input() cssCardHeight: number;


  constructor() {
   }

  ngOnInit() {
  }

}

action-thumbnail.component.html

<div *ngIf="cssCardHeight === 0;then small else large"></div>
<ng-template #large>
  <div class="flip-card card-long" [routerLink]="action.navURL" routerLinkActive="router-link-active">
    <div class="flip-card-inner text-center">

      <div class="flip-card-front card-long" style="padding:20%">
        <img class="img-responsive" [src]='action.imageURL' alt="Card image cap">
        <br />
        <h5 class="card-text" style="letter-spacing: 1px; color: black; font-size: 16px;">{{action.description}}</h5>
      </div>

      <div class="flip-card-back card-long">
        <div class="card-body">
          <h3 class="card-title" style="padding: 3%;">{{action.description}}</h3>
          <h5 class="card-text">Description for this option goes here.</h5>
        </div>
      </div>

    </div>
  </div>

</ng-template>

<ng-template #small>
  <div class="flip-card card-small" [routerLink]="action.navURL" routerLinkActive="router-link-active">
    <div class="flip-card-inner text-center">

      <div class="flip-card-front card-small" style="padding:20%">
        <img class="img-responsive" [src]='action.imageURL' alt="Card image cap">
        <br />
        <h5 class="card-text" style="letter-spacing: 1px; color: black; font-size: 16px;">{{action.description}}</h5>
      </div>

      <div class="flip-card-back card-small">
        <div class="card-body">
          <h3 class="card-title" style="padding: 3%;">{{action.description}}</h3>
          <h5 class="card-text">Description for this option goes here.</h5>
        </div>
      </div>

    </div>
  </div>

</ng-template>

router.ts

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full'},
  {
    path: 'home',
    component: ActionsListComponent,
    data : {
       breadcrumb : 'Home'
    },
    children: [
      {
      path: 'settings',
      component: ActionsListComponent,
      data: {
        breadcrumb: 'Settings',
        imageURL: './assets/images/settings.png'
      },
      children: [
      {
        path: 'sub-option1',
        component: OP1,
        data: {
          breadcrumb: 'Option 1',
          imageURL: './assets/images/o1.png'
        }
      },
      {
        path: 'sub-option2',
        component: Op2,
        data: {
          breadcrumb: 'Option 2',
          imageURL: './assets/images/o2.png'
        }
      }]
    },
    {
      path: 'o1',
      component: Option1,
      data: {
        breadcrumb: 'option 1'
      }
    },
    {
      path: 'o2',
      component: Option2,
      data: {
        breadcrumb: 'option 2'
      }
    },
    {
      path: 'o3',
      component: Option3,
      data: {
        breadcrumb: 'option 3' 
     }
    }]
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

export class PMRoutingModule { }

我的问题,

使用上述结构,我无法决定将<router-outlet>放置在何处以加载各个子选项或功能。

0 个答案:

没有答案