角度自定义控件-星级-输入值

时间:2018-11-11 11:11:17

标签: angular typescript angular-material

<div class="rating">
<div style="display: inline-block"
  *ngFor="let starred of stars; let i = index"
  (click)="rate(i + (starred ? (value > i + 1 ? 1 : 0) : 1))">
      <ng-container *ngIf="starred; else noStar"><mat-icon class="filled">star</mat-icon></ng-container>
      <ng-template #noStar><mat-icon class="empty">star_outline</mat-icon></ng-template>
    </div>
</div>   


 @Component({
  selector: 'jfg-star-rating',
  templateUrl: './star-rating.component.html',
  styleUrls: ['./star-rating.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => StarRatingComponent),
      multi: true
    }
  ]

})
export class StarRatingComponent implements ControlValueAccessor{

  stars: boolean[] = Array(3).fill(true);

   // Allow the input to be disabled, and when it is make it somewhat transparent.
  @Input() disabled = false;
   @HostBinding('style.opacity')
   get opacity() {
     return this.disabled ? 1 : 1;
   }

   // Function to call when the rating changes.
   onChange = (rating: number) => {
   };

   // Function to call when the input is touched (when a star is clicked).
   onTouched = () => {
   };


   get value(): number {
     if(!this.disabled){
     return this.stars.reduce((total, starred) => {
       return total + (starred ? 1 : 0);
     }, 0);
     }
   }
   rate(rating: number) {
     if (!this.disabled) {
       this.writeValue(rating);
     }
   }

   // Allows Angular to update the model (rating).
   // Update the model and changes needed for the view here.
   writeValue(rating: number): void {
     if (!this.disabled) {
       this.stars = this.stars.map((_, i) => rating > i);
       this.onChange(this.value);
     }

   }

   // Allows Angular to register a function to call when the model (rating) changes.
   // Save the function as a property to call later here.
   registerOnChange(fn: (rating: number) => void): void {
     this.onChange = fn;
   }

   // Allows Angular to register a function to call when the input has been touched.
   // Save the function as a property to call later here.
   registerOnTouched(fn: () => void): void {
     this.onTouched = fn;
   }

   // Allows Angular to disable the input.
   setDisabledState(isDisabled: boolean): void {
     this.disabled = isDisabled;


   }
 }

我正在尝试为星级评分。我让它可以正常工作作为输入。因此,我可以按星号以获取正确的值作为formControl并将其传递给我的服务。但是我的问题是我试图使我的组件以@input的形式获取值,并根据该值设置星数。我尝试输入该值并将其设置为我可以但仍无效果的任何地方。如果您可以建议我如何继续从输入中设置值,我会很高兴:)

1 个答案:

答案 0 :(得分:2)

您已经实现了ControlValueAccessor,因此应该能够通过ngModel设置值,这是两个绑定。您不需要任何其他输入即可设置该值。因此,您可以将StarRatingComponent用作-

<jfg-star-rating [ngModel]="3"></jfg-star-rating>

OR

<jfg-star-rating [(ngModel)]="rating"></jfg-star-rating>

工作副本在这里-https://stackblitz.com/edit/angular-material-sample-vv4s6b