【问题标题】:Angular 6 Dropdown inside Material Tabs Error材料选项卡错误中的 Angular 6 下拉菜单
【发布时间】:2018-10-08 16:53:17
【问题描述】:

我有一个输入下拉组件,它在同一个应用程序的多个位置使用,但在不同的选项卡中。

我面临的问题是,当我从选项卡 1 的下拉列表中选择一个值并使用该值完成 API 调用时,选项卡 2 中的相同组件也使用选项卡 1 中的选定值执行此操作。

当我在不同的标签中订阅相同的服务时,如何解决这个问题?

<ng-select 
  [items]="Groups"
  [virtualScroll]="true"
  bindLabel="bg_desc"
  bindValue="bg_desc"
  placeholder="Groups"
  [(ngModel)]="selectedGroup"
  [clearable]="false"
  (change)="selectGroups()">
  <ng-template 
    ng-notfound-tmp 
    let-searchTerm="searchTerm">
    <div class="ng-option disabled">
      No data found for "{{searchTerm}}"
    </div>
  </ng-template>
  <ng-template 
    ng-option-tmp 
    let-item="item" 
    let-search="searchTerm">
    <div 
      [ngOptionHighlight]="search" 
      class="text-uppercase">
      {{item.bg_desc}}
    </div>
  </ng-template>
</ng-select>

这是在我的组件中:

selectGroups() {
  this._data.changeGroup(this.selectedGroup);
}

这是我的服务:

changeGroup(bg: string) {
  this.changeGroupData.next(bg);
}

private changeGroupData = new BehaviorSubject<string>('');
currentChangeGroupData = this.changeGroupData.asObservable();

这是我的 stackbliz 示例:https://stackblitz.com/edit/angular-1oucud

我希望在这些选项卡上单独调用。我应该创建三个具有不同名称的相同组件实例来实现这一点吗?

【问题讨论】:

    标签: javascript html angular rxjs angular-material


    【解决方案1】:

    考虑一下您的程序的架构? DropDownComponent 真的应该在模型更改后更新服务,还是更像是一个更具体的输入控件,并且任何绑定或应用程序逻辑都应该发生在它之外?

    在我看来,第二种情况更合适,特别是如果您觉得需要重用它。您可以轻松地将 DropDownComponent 修改为具有 Input 和 Output 并将外部组件绑定到它。或者你可以加倍努力,让你的组件扩展 NgModelAccessor,这样你就可以在表单中正确使用它。

    我将在下面给出一个更简单方法的示例。

    • DropDownComponent 将更改为完全独立。它具有其他组件将绑定到的输入和输出。
    • AppComponent 有一个模型,模型的属性绑定到视图中的下拉列表实例。没有特别的原因,我也绑定到 change 事件只是为了向您展示会发生什么。这实际上是没有必要的,因为执行“banana-in-a-box”语法会导致输出按照约定绑定 - 输出与输入具有相同的名称,并在末尾附加了更改。

    DropDownComponent.ts

    export class DropdownComponent  {
      colors = colors;
    
      @Input() selectedColor;
      @Output() selectedColorChange = new EventEmitter<string>();
    
      changeColor(e) {
        this.selectedColorChange.emit(this.selectedColor);
      }
    }
    

    AppComponent.ts

    declare type ColorType = { color: string, value: string };
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      colors: { first?: ColorType, second?: ColorType, third?: ColorType } = {};
    
      doSomething(colorKey: string) {
        console.log(`The color changed was ${colorKey} with a value of ${this.colors[colorKey].value}.`)
      }
    }
    

    AppComponent.html

    <mat-tab-group>
        <mat-tab label="First">
            <dropdown [(selectedColor)]="colors.first" (selectedColorChange)="doSomething('first')"></dropdown>
        <p>Selected Color is {{colors.first?.color}}</p>
        </mat-tab>
        <mat-tab label="Second">
            <dropdown [(selectedColor)]="colors.second" (selectedColorChange)="doSomething('second')"></dropdown>
        <p>Selected Color is {{colors.second?.color}}</p>
        </mat-tab>
        <mat-tab label="Third">
            <dropdown [(selectedColor)]="colors.third" (selectedColorChange)="doSomething('third')"></dropdown>
        <p>Selected Color is {{colors.third?.color}}</p>
        </mat-tab>
    </mat-tab-group>
    

    【讨论】:

    • 明白。在某些情况下,我有几个下拉列表,它们根据前一个下拉列表的值获取过滤器。这是我使用共享服务的主要原因。
    • 我会认为你是 Angular 开发的新手。有意识地减少相互依赖。您可以让服务保持状态 - 这是完全可以接受的,但仅在必要时尝试这样做。如果您有选项被表单上的其他选择过滤,则将项目传递一个输入属性并让父表单组件适当地过滤项目。你不应该为此需要状态服务。
    【解决方案2】:

    您只需要使用输出与外部组件进行通信。就是这样

    https://stackblitz.com/edit/angular-1oucud

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-27
      • 2014-12-08
      • 1970-01-01
      • 2020-03-13
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      相关资源
      最近更新 更多