Angular6:在单个页面上的多个位置使用星级评分组件

时间:2019-02-14 13:12:03

标签: html angular

我在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>

1 个答案:

答案 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;
}