I have a ng-template
which is repeated using an *ngFor. I am passing additional data to the template from ngFor using ngTemplateOutletContext
. With this data that I am passing to the template I am creating a dropdown list. I have this stackblitg example showing a code extract of what I have done.
Data
data = {
row1_ID: {
'article 1': 'Lorem Ipsum is simply dummy text ',
'article 2': 'Lorem Ipsum has been the industry standard dummy text ',
},
row2_ID: {
'article 1': 'aldlsadalskjd;asjsa;kdj dalskdjaslkjd',
'article 2': 'Lorem ipsum dolor sit ame',
},
};
HTML
<div *ngFor="let row of data | keyvalue">
<ng-container
[ngTemplateOutlet]="OpRef2"
[ngTemplateOutletContext]="{ data: row.value, id: row.key }">
</ng-container>
</div>
<ng-template #OpRef2 let-data="data" let-id="id">
<div >
<h2>Row ID: {{ id }}</h2>
<select> <!--Using ng model here doesnt work-->
<option *ngFor="let article of data | keyvalue" [value]="article.key">
{{ article.key }}
</option>
</select>
<div>
<!--I would like the contect of this do change based on what's selected in the dropdpwn but varaibles created in the context of ng-template are readonly hence nh-model doesnt work-->
<div>{{ data['article 1'] }}</div>
</div>
Now based on the values selected in the dropdown I want the content below it to change. But since its a template, any varianle I create are readonly and can't be used in the ngModel
for the select
. Also I cant use an external variable list as the rows in the data property are fetched from an API and I cant be sure how many rows it would contain.
Is there any way of achiving this?
CodePudding user response:
If its only to be able to change de between articles you could do it without binding the ngModel to a property and accesing the ngModel value through a template variable.
It would be something like this.
<div >
...
<select ngModel #articleSelected="ngModel">
...
</select>
<div>
<div>{{ data[articleSelected.value] }}</div>
</div>
</div>
Cheers
CodePudding user response:
Case is that you don't have a variable (reference object) to bind ngModel to.
I have done a simple implementation for you using a separate map as collection of reference. I used the data to create the map of references dynamically too.
Have a look at this stackblitz
HTML
<ng-template #OpRef2 let-data="data" let-id="id">
<div >
<h2>Row ID: {{ id }}</h2>
<select [(ngModel)]="valueHolders.get(id).value">
<!--Using ng model here doesnt work-->
<option *ngFor="let article of data | keyvalue" [value]="article.key">
{{ article.key }}
</option>
</select>
<!--I would like the contect of this do change based on what's selected in the dropdpwn but varaibles created in the context of ng-template are readonly hence nh-model doesnt work-->
<div>{{ data[valueHolders.get(id).value] }}</div>
</div>
</ng-template>
TS
valueHolders = new Map<string, ValueHolder>();
createValueHoldersByData(){
Object.keys(this.data).forEach(key=>{
const valueHolder = new ValueHolder(key, Object.keys(this.data[key])[0]);
this.valueHolders.set(key, valueHolder);
});
}
export class ValueHolder{
key: string;
value: string;
constructor(key: string, value: string){
this.key = key;
this.value = value;
}
}
CodePudding user response:
I would suggest creating a new property in your component class (e.g. selectedData
) to hold the selected value from the dropdowns, then, binding the ngModel
to it by id
.
You can try something like the following:
<!--
In your component class, define a selectedData with and assign an empty object to it,
to be used in the component's template: `selectedData = {};`
-->
<ng-template #OpRef2 let-data="data" let-id="id">
<div >
<h2>Row ID: {{ id }}</h2>
<!-- Use ngModel to bind to the selected value -->
<select [(ngModel)]="selectedData[id]">
<option *ngFor="let article of data | keyvalue" [value]="article.key">
{{ article.key }}
</option>
</select>
<div>
<!-- Here we can use the selected[id] to bind to the selected value -->
<div>{{ data[selectedData[id]] }}</div>
</div>
</div>
</ng-template>