我在AngularJS应用程序中使用星级评定组件。我面临的问题非常简单。我的表单是动态的,并且根据输入的类型生成表单。我使用了here中的评分成分。一切正常。问题是在示例中,问题是一次生成的。这是使用项目数组生成的。我的问题是我不想一次显示所有基于评分的问题。例如,问题1可能具有响应类型“文本”,问题2可能是评级,问题3可能是单选按钮,问题4可能是评级。我用来生成表单的代码是:
<div *ngFor="let question of questions">
<!-- Questions having no parent questions: -->
<div class="form-group" *ngIf="question.inputtype === 'textBox'">
<label class="control-label col-sm-4 black" for={{question.id}}>{{question.question}}</label>
<input type="text" class="form-control" data-toggle="tooltip" placeholder={{question.placeholder}} [(ngModel)]="model[question.id]"
name={{question.id}}>
</div>
<div class="form-group" *ngIf="question.inputtype === 'checkbox'">
<label class="control-label col-sm-4 black">{{question.question}}</label>
<div *ngFor="let option of question.options">
<label class="control-label black" for={{option}}>{{option}}</label>
<input type="checkbox" class="" data-toggle="tooltip" name={{option}} [(ngModel)]="model[question.id][option]">
</div>
</div>
<div class="form-group" *ngIf="question.inputtype === 'starRating'">
<label class="control-label col-sm-4 black">{{question.question}}</label>
<div>
<app-rating [rating]='item.rating' [itemId]='item.id' (ratingClick)='ratingComponentClick($event)'></app-rating>
</div>
</div>
</div>
答案 0 :(得分:0)
据我了解,您希望以相同的形式使用上面多次共享的代码段来呈现一系列“问题”对象。但是,由于该片段包含一个*ngFor
,因此它会一次遍历所有问题。为了解决这个问题,我将引入一个<app-question/>
组件来呈现单个问题
@Component({
selector: 'app-question',
templateUrl: './question.component.html',
styleUrls: [ './question.component.css' ]
})
export class QuestionComponent {
@Input()
model: any//the model to bind to
@Input()
question: any// the question object to read
ratingComponentClick($event){
this.model[this.question.id] = $event.rating;//somehow map the value to the model
}
}
question.component.html:
<!-- Questions having no parent questions: -->
<div class="form-group" *ngIf="question.inputtype === 'textBox'">
<label class="control-label col-sm-4 black" for={{question.id}}>{{question.question}}</label>
<input type="text" class="form-control" data-toggle="tooltip" placeholder={{question.placeholder}} [(ngModel)]="model[question.id]"
name={{question.id}}>
</div>
<div class="form-group" *ngIf="question.inputtype === 'checkbox'">
<label class="control-label col-sm-4 black">{{question.question}}</label>
<div *ngFor="let option of question.options">
<label class="control-label black" for={{option}}>{{option}}</label>
<input type="checkbox" class="" data-toggle="tooltip" name={{option}} [(ngModel)]="model[question.id][option]">
</div>
</div>
<div class="form-group" *ngIf="question.inputtype === 'starRating'">
<label class="control-label col-sm-4 black">{{question.question}}</label>
<div>
<app-rating [rating]='question.rating' [itemId]='question.id' (ratingClick)='ratingComponentClick($event)'></app-rating>
</div>
</div>
然后您可以在任意位置和任意位置使用该新组件多次:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
myModel = {}
questions = [
{ id: 'question1', rating: 3, question: 'Rate Angular', inputtype: 'starRating' },
{ id: 'question2', question: 'Does this answer your question?', inputtype: 'textBox' },
{ id: 'question3', rating: 1, question: 'Rate my answer', inputtype: 'starRating' }
];
}
app.component.html:
<h1>Reusable Question Component</h1>
<app-question [model]="myModel" [question]="questions[0]"></app-question>
<br>
<label>Here's another input</label>
<input type="text" name="myInput" [(ngModel)]="myModel.myInput">
<br>
<app-question [model]="myModel" [question]="questions[1]"></app-question>
<br>
<app-question [model]="myModel" [question]="questions[2]"></app-question>
<h2>Edit form to change model:</h2>
<pre>
{{myModel | json}}
</pre>
Here's a working version of the code。这里的主要收获是职责分离:有一个组成部分包含问题,另一个包含单个问题。 但是,这不是最佳解决方案,因为它不能使您充分控制表单验证。更好的解决方案是使用Reactive Forms,因为它们是针对这种用例而设计的。 Angular的官方文档包含一个值得阅读covering your very same use case的教程。不幸的是,我认为涵盖这些主题将超出此问题的范围,因此,如果您对反应形式还有其他疑问,请使用搜索或提出其他问题。我希望这会有所帮助!
P.S。我更改了rating.component.css
来清除浮点数:
:host::after{
content: "";
clear: both;
display: table;
}