user2741109 user2741109 - 3 months ago 53
TypeScript Question

angular2 – using same component as nested components with different inputs multiple times in single parent component

I am trying to use a bootstrap popup component as nested component multiple times on a single page. This popup component takes different values as

@Input()
. The problem is that every popup on the page has the same values as the last popup. So, how can I get multiple instances of the same nested component?

Here is the parent component:

@Component({
selector: 'my-parent',
templateUrl: 'app/components/parent/parent.component.html',
directives: [PopupDirective]
})
export class ParentComponent {
private doSomething() {
// do something
}
}


This is the html of my parent component:

<button class="btn btn-success"
(click)="popup1.show()">Call Popup 1</button>

<button class="btn btn-success"
(click)="popup2.show()">Call Popup 2</button>

<my-popup #popup1
[id]="1"
[title]="Popup 1"
[body]="This is my test popup 1"
(confirmation)="doSomething()"></my-popup>

<my-popup #popup2
[id]="2"
[title]="Popup 2"
[body]="This is my test popup 2"
(confirmation)="doSomething()"></my-popup>


Here is the popup component:

@Component({
selector: 'my-popup',
templateUrl: 'app/directives/popup/popup.directive.html'
})
export class PopupDirective {

@Input() id: string;

@Input() title: string;
@Input() body: any;

@Output() confirmation: EventEmitter<string> = new EventEmitter<string>();

private triggerPopup: string;

constructor() {
this.triggerPopup = "triggerPopup";
}

confirm() {
this.confirmation.emit('Click from nested component');
}


show() {
document.getElementById(this.triggerPopup).click();
}
}


And finally the html code of my popup

<a id="{{ triggerPopup }}"
href="#popup{{ id }}"
data-toggle="modal"
[hidden]="true"></a>

<div class="modal fade" id="popup{{ id }}" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4>{{ title }}</h4>
</div>
<div class="modal-body">
<div>{{ body }}</div>
<div style="clear: both;"></div>
</div>
<div class="modal-footer">
<a class="bin ban-default"
data-dismiss="modal">
Close</a>

<a class="bin ban-success"
data-dismiss="modal"
(click)="confirm()">
Confirm</a>
</div>
</div>
</div>
</div>

Answer

You are assigning the same id to each element

constructor() {
    this.triggerPopup = "triggerPopup";
}

and therefore

document.getElementById(this.triggerPopup).click();

always finds the first one because it searches the whole page and doesn't care about component boundaries.

I'd suggest to use template variables and @ViewChild() instead

<a #triggerPopup"
export class PopupDirective {
  @ViewChild('triggerPopup') triggerPopup:ElementRef;

  show() {
    this.triggerPopup.nativeElement.click();
  }
Comments