角@ViewChild魔术

时间:2018-11-15 13:01:21

标签: angular typescript

我有一个递归呈现的嵌套菜单。我需要对父元素设置活动类,以便对其施加压力。我正在尝试通过将routerLinkActive分配给id,然后通过@ViewChild从组件检查它来实现这一目标。

<ng-container routerLinkActive #rla="routerLinkActive" [routerLinkActiveOptions]="{exact: true}">
  <li [class.active]="rla.isActive || isActive">
    <a [routerLink]="menuItem.link" *ngIf="menuItem.link; else noLink">
      <i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
      {{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
    </a>
    <ng-container *ngIf="menuItem.children && menuItem.children.length > 0">
      <ul class="nav child_menu" [class.active]="isActive || rla.isActive"
          *ngFor="let item of menuItem.children">
        <app-menu-item [menuItem]="item" (checkActive)="updateActiveState()"></app-menu-item>
      </ul>
    </ng-container>
  </li>

  <!--In case there is no link provided (has children)-->
  <ng-template #noLink>
    <li [class.active]="isActive">
      <a (click)="toggleActive()">
        <i *ngIf="menuItem.faClass" class="fa fa-{{menuItem.faClass}}"></i>
        {{menuItem.name}} <span *ngIf="menuItem.children && menuItem.children.length > 0" class="fa fa-chevron-down"></span>
      </a>
    </li>
  </ng-template>
</ng-container>

这是我的组件

public menuSize;
  public isActive = false;

  @Input() menuItem: MenuItem;
  // @Input() routerActive: boolean;

  @ViewChild('rla') routerActive;

  @Output() checkActive: EventEmitter<void> = new EventEmitter<void>();
  @ViewChild(MenuItemComponent) menuComponent: MenuItemComponent;

  private hostActive = true;
  private hostActiveSm = false;

  constructor(
    private router: Router,
    private uss: UiStateService,
  ) {
  }

  ngOnInit() {
    this.uss.menuSubject.subscribe(msg => {
      this.menuSize = msg;
      if (this.menuSize === MenuSizes.sm) {
        this.hostActive = false;
        this.hostActiveSm = true;
      } else {
        this.hostActive = true;
        this.hostActiveSm = false;
      }
    });

    this.router.events.subscribe((e: Event) => {
      if (e instanceof NavigationEnd) {
        this.updateActiveState();
      }
    });
  }

  ngOnChanges() {
  }

  ngAfterViewInit() {
    this.updateActiveState();
    console.log('This is active', this.routerActive);

    if (this.routerActive.isActive) {
      console.log('emitting');
      this.checkActive.emit();
    }
  }

  public toggleActive(): void {
    this.isActive = !this.isActive;
    // if (this.menuComponent) {
    //   this.menuComponent.isActive = true;
    // }
  }

  private updateActiveState(): void {
    // reset previous state
    this.isActive = false;
    if (this.menuComponent) {
      this.menuComponent.isActive = false;
    }

    if (this.menuComponent && this.menuComponent.isActive) {
      // console.log('Menu component');
      // console.log(this.menuComponent, this.menuComponent.menuItem.link);
      this.isActive = true;
    }
  }

问题是当我控制台日志this.routerActive时,浏览器会在激活的路由上打印出具有属性isActive = true的routerLinkActive对象。

enter image description here

但是,如果我尝试控制台日志this.routerActive.isActive,它将显示所有6个错误(好像没有活动的路由)。 enter image description here

更新

只是为了使它更加清晰,这里是更详细的日志 enter image description here

这就是我所拥有的 enter image description here

更新#2

只是尝试分配一个对象,并用isActive = false获得了6个对象

1 个答案:

答案 0 :(得分:0)

如果您有几个类似的组件,则应使用@ViewChildren而不是@ViewChild,

@ViewChildren('rla')
routerActives: QueryList<RouterLinkActive>;

然后遍历它们以找到一个/实现所需结果

this.routerActives.forEach((item) => {
...
});