问题
I am working on an items App. Now, A can transfer items to B. My interface is simple: list of members to chose from as source on left and to whom to give on the right. Since the source of the information, appearance and search functionality is the same, I thought of creating one component that I can use here (and in another component that requires similar interface). Here is a realistic but simplified version:
In parent.ts, html I have:
<div class="col-md-3">
<label>Source</label>
<app-browser></app-browser>
</div>
<div class="col-md-3">
<label>Destination</label>
<app-browser></app-browser>
</div>
The AppBrowser.componenet.ts:
selected_g:number=0; //nothing selected yet.
eventSelect(){
var element=document.ElementByID('data') as HTMLSelectElement;
let value:number=+element.value;
if(value==0){
alert('Make a selection');
return false;
}
this.selected_g=value;
}
the template:
<select id="data">
<option value="0">Select One</option>
<option value="1">G1</option>
<option value="2">G2</option>
</select>
<button (click)="eventSelect()">Confirm</button>
Now the problem is: if I select a valid option in the first (source i.e. the instance I inserted first), the second instance (destination) has no effect. That is, I can select value 0 and click Confirm and it wouldn't complain. It would complain if the first instance has selected 0 only. I was under the impression components are like classes: if I insert the components multiple times, each one would work in its own right/space. But it appears only the first instance manages the whole thing. Am I mistaken?
回答1:
There are 2 issues here. The first is the same issue raised at How to reuse an angular component multiple times - angular will process only one DOM element for the root component - so you can't have more than one <app-browser>
tag. However it works if you move the select code into a sub-component - see this plunkr demo
The 2nd issue is that you are using id="data"
in select
in the template. Since you are then trying to fetch it using document.getElementById('data')
it will always return the first one it finds. This means that if the first field is unselected, then even if you change the 2nd one the alert will always fire since the first id
is the first one returned from the document.
To fix this you need a unique id for each instance of the component. You could do this manually, e.g. <my-sub [id]="xxx">
or posisbly generate it dynamically.
In angular 1.x this could be done with $id
- I'm not sure what the correct way to do this in 2+ is - but you could do worse than use e.g. Math.random()
Here's a modification of the original example using Math.random()
: plunkr demo
Finally, it might only be applicable to this instance, but the effect of repeating the component could be done in other ways - for example using ngFor
in the root
or sub
component, providing arguments (including an id
) if useful.
来源:https://stackoverflow.com/questions/48370756/using-a-component-more-than-once-in-a-single-parent-component