【问题标题】:Angular - Control angular tab using dropdown optionAngular - 使用下拉选项控制角度选项卡
【发布时间】:2021-10-10 00:57:50
【问题描述】:

创建了一个选项卡组件,允许用户添加多个选项卡,并且在单击选项卡标题时将填充单个选项卡信息,这可以正常工作,没有任何问题。

我想使用下拉选择选项控制/管理标签点击。

stackblitz

app.component.ts

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

import { TabsComponent } from './tabs/tabs.component';

@Component({
  selector: 'my-app',
  template: `
    {{ message }}
    <select
      id="select-menu-0"
      class="services-select"
      autoComplete="address-level1"
      (change)="handleDropdown($event)"
    >
    <option *ngFor="let item of options; index as i">
    {{item}}
  </option>
    </select>
    <my-tabs (onSelect)="handleTabClick($event)" [selectedIndex]="selectedTab">
      <my-tab [tabTitle]="'Tab 1'">
        Tab 1 content
      </my-tab>
      <my-tab tabTitle="Tab 2">
        Tab 2 content
      </my-tab>
      <my-tab tabTitle="Tab 3">
        Tab 3 content
      </my-tab>
    </my-tabs>
  `
})
export class AppComponent {
  message: string;
  selectedTab: number = 2;
  options: Array<string> = ['Tab 1', 'Tab 2', 'Tab 3'];

  handleTabClick(event) {
    console.log('$evnt', event);
    this.message = `${event.title} is clicked`;
  }

  handleDropdown(event) {
    console.log('EVENT', event.target.value, this.options.indexOf(event.target.value));
    this.selectedTab = this.options.indexOf(event.target.value);
    this.message = `${event.target.value} is clicked`;
    // this.handleTabClick(event);
  }
}

tabs.component.ts

import {
  Component,
  ContentChildren,
  QueryList,
  AfterContentInit,
  ViewChild,
  ComponentFactoryResolver,
  ViewContainerRef,
  Input,
  Output,
  EventEmitter
} from '@angular/core';

import { TabComponent } from './tab.component';
import { DynamicTabsDirective } from './dynamic-tabs.directive';

@Component({
  selector: 'my-tabs',
  template: `
    <ul class="nav nav-tabs">
      <li *ngFor="let tab of tabs" (click)="sendMessage(tab)" [class.active]="tab.active">
        <a href="#">{{tab.title}}</a>
      </li>
    </ul>
    <ng-content></ng-content>
  `,
  styles: [
    `
    .tab-close {
      color: gray;
      text-align: right;
      cursor: pointer;
    }
    `
  ]
})
export class TabsComponent implements AfterContentInit {

  @Input() selectedIndex: number;
  @Output() onSelect = new EventEmitter<string>();

  sendMessage(tab: Tab) {
    console.log('this.tabs', this.tabs.first, this.tabs.last);
    this.onSelect.emit(tab);
    this.tabs.toArray().forEach(tab => tab.active = false);
    tab.active = true;
  }
  
  @ContentChildren(TabComponent) tabs: QueryList<TabComponent>;
  
  // contentChildren are set
  ngAfterContentInit() {
    // get all active tabs
    console.log('selectedIndex', this.selectedIndex, typeof this.selectedIndex);
    console.log('ngAfter', this.tabs, this.tabs.toArray());
    let activeTabs = this.tabs.filter((tab)=>{ console.log('TBB', tab); return tab.active});
    console.log('activeTabs', activeTabs);

    if (this.selectedIndex) {
      console.log('SELECEELTLLT', this.tabs.toArray()[this.selectedIndex]);
      this.selectTab(this.tabs.toArray()[this.selectedIndex]);
    } else {
      this.selectTab(this.tabs.first);
    }
    
    // if there is no active tab set, activate the first
    // if(activeTabs.length === 0) {
    //   this.selectTab(this.tabs.first);
    // }
  }
  
  selectTab(tab: Tab){
    // deactivate all tabs
    console.log('tab', tab);
    this.tabs.toArray().forEach(tab => tab.active = false);
    
    // activate the tab the user has clicked on.
    tab.active = true;
  }
}

【问题讨论】:

    标签: javascript angular select tabs angular-components


    【解决方案1】:

    我假设您想使用SELECT 元素处理TAB 更改过程,我检查了您已经实现Parent Child Component Communication 的代码。现在您的父组件中有一个选择下拉列表,我相信您在处理子组件中选择下拉列表的更改事件时遇到了问题,

    我注意到您正在将selectedIndex 传递给您的子组件,现在每当发生选择下拉菜单的更改事件时,您也在修改selectedIndex 的值,因此请尝试实现OnChange 接口 与您的子组件,

    修改tabs.component.ts文件:

    现在提供 OnChange 接口的实现,通过定义如下方法

    现在,如果您尝试更改选择下拉值,它也会更改选项卡,

    【讨论】:

    • 问题与OnChanges无关
    • 好的!我建议一种方法,您也可以通过这种方式实现您的期望,但是我可以知道,您为什么不想使用这个OnChanges
    • 你说得对,我认为问题与 OnChanges 无关,是另一种我不认为的方法,感谢您的建议 - 以及课程 - (如果只有一个输入建议使用二传手,但也是一个很好的方法)
    • 不客气!
    • @SuneelKumar 该解决方案按预期工作。
    【解决方案2】:

    我建议另一种方法:通过“selectedIndex”控制所有

    如果你定义了一个@Input 和一个@Output 类似

      private _selectedIndex: number;
      @Input() set selectedIndex(value) {
        if (this.tabs && this.selectedIndex != value) {
          this._selectedIndex = value;                    //equal an auxiliar variable
          const tab=this.tabs.find((_x, i) => i == value);//find the "tab"
          if (tab){
              this.selectTab(tab);                            //call to selectTab
              this.onSelect.emit(tab);                        //emit onSelect
              this.selectedIndexChange.emit(value)            //emit selectedIndexChange
          }
        }
      }
      get selectedIndex(){
        return this._selectedIndex   //simple return the variable
      }
    
      @Output() selectedIndexChange = new EventEmitter<number>();
      @Output() onSelect = new EventEmitter<TabComponent>();
    

    代码变得更简单了。

      //In the tabs.component.html just change the selectedIndex
     <li
        *ngFor="let tab of tabs;let i=index"
        (click)="this.selectedIndex=i"
        [class.active]="tab.active"
      >
    
      //and in tabs.component.ts
      ngAfterContentInit() {
        if (this.selectedIndex) {
          this.selectTab(this.tabs.find((_x, i) => i == this.selectedIndex));
        } else {
          this.selectTab(this.tabs.first);
        }
      }
    
      selectTab(tab: Tab) {
        this.tabs.forEach(x => (x.active = x == tab));
      }
    

    你可以在你的 main.app 中使用(注意你需要 import FormsModule 才能使用 [(ngModel)])

    <!--simple use [(ngModel)]-->
    <select [(ngModel)]="selectedTab">
        <option *ngFor="let item of options; index as i" [value]="i">
          {{item}}
        </option>
    </select>
    
    <!--see the "bannana" notation in selectedIndex-->
    <my-tabs (onSelect)="handleTabClick($event)" [(selectedIndex)]="selectedTab" >
         ....
    </my-tabs>
    

    你的forked stackblitz

    注意:看到你不需要convertToArray QueryList,你可以使用语法this.tabs.find((x,index)=&gt;{...})并使用“index”

    【讨论】:

    • 另一种方法有效,有助于减少几行代码。
    猜你喜欢
    • 2018-06-13
    • 2015-09-12
    • 1970-01-01
    • 2019-04-07
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-23
    相关资源
    最近更新 更多