简体   繁体   中英

Angular 6 Dropdown inside Material Tabs Error

I have an input drop-down component which is used in multiple places in the same app but in different tabs.

The issue I am facing is when I select a value from the drop-down in Tab 1 and an API call is done with the value, the same component in Tab 2 also does that with the selected value in Tab1.

How do I fix this as I am subscribing to the same service in the different tabs?

<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>

This is in my component:

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

This is my service:

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

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

This is my stackbliz example: https://stackblitz.com/edit/angular-1oucud

I want individual calls on these tabs. Should I create three instances of same component with different names to achieve this?

Think about the architecture of your program? Should DropDownComponent really be updating a service after a model change or is more like a more specific input control and any binding or application logic should occur outside of it?

It seems to me that the second case is more appropriate, especially if you feel the need to reuse it. You can easily modify the DropDownComponent to have an Input and Output and have the outer component bind to it. Or you can go the extra mile and have your component extend NgModelAccessor, so you can use it properly in forms.

I'll give an example of the simpler approach below.

  • DropDownComponent is to changed to be completely standalone. It has an input and output that other components will bind to.
  • AppComponent has a model and the properties of the model are bound to instances of dropdown in the view. For no particular reason I also bound to the change event just to show you what happens. It really isn't necessary as doing the banana-in-a-box syntax will cause the Output to be bound to by convention - the Output having the same name as the input with Change appended to the end.

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>

You just need to use output to communicate to outer component. Thats it

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM