首页 > 解决方案 > 角度自定义控件 - 星级 - 来自输入的值

问题描述

<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 获取值并根据该值设置星数。我已经尝试输入值并将其设置在我可以设置的任何地方,但仍然没有效果。如果您能建议我如何继续从输入中设置值,我会很高兴:)

标签: angulartypescriptangular-material

解决方案


您已经实现ControlValueAccessor了,因此您应该能够设置ngModel两个绑定的值。您不需要任何其他输入来设置该值。所以你可以使用你StarRatingComponent的 -

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

或者

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

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


推荐阅读