#javascript #angular #typescript
#javascript #угловой #typescript
Вопрос:
У меня есть фрагмент JSON, который представляет некоторые действия и параметры, которые может установить пользователь.
Я хочу отобразить действия в выпадающем списке, и когда пользователь выбирает один — отображаются требуемые параметры, связанные с действием.
Пример:
- Пользователь выбирает действие с одним параметром, отображается единственное поле ввода
- Пользователь выбирает действие с двумя параметрами, отображаются два поля ввода.
У меня почти получилось, но *ngFor
не отображаются входные данные для выбранного действия:
В onChange
— если я печатаю this.steps
, я вижу, что this.steps[i].SelectedAction.UIParameters
имеет значение, поэтому я не уверен, почему оно не отображается.
JSON:
[
{
"ActionEnum": "CLICKELEMENT",
"Name": "Click Element",
"UIParameters": [
{
"ParameterEnum": "ELEMENTID",
"Description": "The id of the element to click"
}
]
},
{
"ActionEnum": "INPUTTEXT",
"Name": "Input Text",
"Description": "Enters text into the element identified by it's id",
"UIParameters": [
{
"ParameterEnum": "ELEMENTID",
"Description": "The id of the element"
},
{
"ParameterEnum": "TEXTVALUE",
"Description": "The text to enter into the element"
}
]
}
]
Typescript:
import { Component, Output, EventEmitter, OnInit } from "@angular/core";
import { ActionService } from "../services/action-service";
import { Action } from "../models/Action";
@Component({
selector: 'app-scenario-step-editor-component',
template: `
<form #formRef="ngForm">
<div *ngFor="let step of steps; let in=index" class="col-sm-3">
<div class="form-group">
<label class="sbw_light">Action:</label><br />
<select (change)='onChange()' [(ngModel)]="step.Action" name="action_name_{{in}}">
<option *ngFor="let action of this.availableActions" [(ngModel)]="steps[in].value" name="action_name_{{in}}" class="form-control" required>
{{action.Name}}
</option>
</select>
<div *ngIf="steps[in].SelectedAction">
<label class="sbw_light">Parameters:</label><br />
<ng-template *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-template>
</div>
</div>
</div>
<button id="addStepBtn" type="button" class="btn btn-light" (click)="addScenarioStep()">Add Scenario Step </button>
</form>`
})
export class ScenarioStepEditorComponent implements OnInit {
@Output() onSelectValue = new EventEmitter<{stepInputs: any[]}>();
steps = [];
availableActions: Action[];
constructor(private actionService: ActionService) {}
ngOnInit(): void {
this.actionService.list().subscribe( result => {
this.availableActions = resu<
},
error => console.log('Error getting actions...') );
}
/* When user picks an option, save the chosen action with the rest of the parameters*/
onChange() {
for (let i = 0; i < this.steps.length; i ) {
let actionIndex = this.availableActions.findIndex(a => a.Name === this.steps[i].Action);
this.steps[i].SelectedAction = this.availableActions[actionIndex];
}
this.onSelectValue.emit( {stepInputs: this.steps} );
}
addScenarioStep() {
this.steps.push({value: ''});
}
}
Комментарии:
1. почему вы используете
ng-template
? возможно, вы хотелиng-container
вместо этого?..2. Это сработало! Как вы узнали? Должно быть, я просто скопировал ее куда-то, не осознавая..
3.
ng-template
не предполагается, что она используется для такого поведения.ng-template
используется для условного отображения некоторого содержимого или для предоставления содержимого другим элементам angular. Конкретно для вашего сценария,ng-container
был подходящим элементом для использования 😉
Ответ №1:
<ng-template *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-template>
Просто замените ng-template
на ng-container
:
<ng-container *ngFor="let parameter of steps[in].SelectedAction.UIParameters">
<label class="sbw_light">{{parameter.ParameterEnum}}</label><br />
<input (change)='onChange()' type="text" [(ngModel)]="steps[in].Parameters" name="parameter_name_{{in}}" class="form-control" #name="ngModel" required />
</ng-container>
Причины:
ng-container
подходит для этой ситуации. Он просто содержит «что-то» и может быть повторен.ng-template
определяет шаблон. Здесь вам не нужен шаблон, шаблоны не предназначены для этого. Конечно, это может сработать, но это не подходит для вашего сценария.
Подробнее о ng-template
и ng-container
читайте здесь: https://blog.angular-university.io/angular-ng-template-ng-container-ngtemplateoutlet /
В качестве последнего примечания, вы могли бы использовать ng-template
путем определения элемента, и вы могли бы использовать ng-container
with *ngTemplateOutlet
для отображения шаблона. Проверьте приведенное выше руководство для некоторых примеров.