angular - 页面初始化时触发 ngb-raring 上的rateChange

标签 angular typescript ng-bootstrap

我对 Angular 很陌生, 我正在尝试使用 ngb-Rating 中的 RateChange 向数据库发送一个新的费率,但它在从服务器获取值时已被触发,例如当我尝试 console.log 费率时,它会打印我从中获得的费率数据库。

这是 Html 模板:

<div class="card-group d-flex  justify-content-center">

    <div class="row justify-content-center">

        <div *ngFor="let item of items" class="col-sm-4  card bg-light"
            style=" max-width: 17rem; border:none; display: flex;margin: 30px;">

            <div class="card-img-top" style="height: 45%; white-space: nowrap;">
                <span class="helper"></span>
                <img src="{{item.image}}" style="margin: 0px; vertical-align: middle; display: inline-block;"
                    width="100%" alt="item.Name">
            </div>
            <div class="card-body">
                <h5 class="card-title" style="text-align: center;">{{item.Name}}</h5>
                <p class="card-description" style="height: 30%;">{{item.Description | Summery}}</p>
                <h5 class="card-text  price" style=" margin: 0px 0px 20px 0px ;">{{item.price | currency}}
                </h5>
                <ngb-rating [max]='5' [(rate)]="item.stars" *ngIf="" (rateChange)="onRateChange($event)">
                    <ng-template let-fill="fill">
                        <span class="star" [class.filled]="fill === 100">&#9733;</span>
                    </ng-template>
                </ngb-rating>
            </div>
            <button class="btn btn-primary mx-auto">add to cart</button>


        </div>
    </div>
</div>

ts 文件:

import { Component, OnInit } from '@angular/core';
import { Item } from 'src/moduls/item';
import { ItemService } from './item.service';

@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css']
})

export class ItemComponent implements OnInit {

  constructor(private itemService: ItemService) { }
  items: any[] = [];
  onRateChange(newRate: number) {
    console.log(newRate);
  }

  ngOnInit(): void {
    this.getItems();
  }



  getItems() {
    return this.itemService.getaData().subscribe(
      Response => {
        this.items = Response as Item[];
        console.log(this.items);
      }
    )
  }

}

最佳答案

ng-bootstrap 实际上是在骗我们。查看评级源代码,我发现只要评级值发生更改,即使用户不参与,也会发出 rateChange

我只看到一种解决方案 - 利用 reactive forms 。您可以订阅valueChanges observable设置初始值后。

import { Component, OnInit, OnDescroy } from '@angular/core';
import { Item } from 'src/moduls/item';
import { ItemService } from './item.service';

@Component({
  selector: 'app-item',
  templateUrl: './item.component.html',
  styleUrls: ['./item.component.css']
})

export class ItemComponent implements OnInit, OnDestroy {
  onDestroy$: Subject = new Subject();
  items: Array<{control: FormControl, item: Item}> = [];

  constructor(private itemService: ItemService) { }

  ngOnInit(): void {
    this.getItems();
  }

  ngOnDestroy(): void {
    this.onDestroy$.next();
  }

  getItems() {
    return this.itemService.getaData().subscribe(
      Response => {
        this.items = (Response as Item[]).map(item => {
           const control = new FormControl(item.stars);
           control.valueChanges
              .tap(takeUntil(this.onDestroy$))
              .subscribe(newRate => this.saveRating(newRate,item));
           return {control, item};
        });
        console.log(this.items);
      }
    )
  }

  saveRating(newRate: number, item: Item) {
    console.log(newRate, item);
  }

}
<div class="card-group d-flex  justify-content-center">

    <div class="row justify-content-center">

        <div *ngFor="let item of items" class="col-sm-4  card bg-light"
            style=" max-width: 17rem; border:none; display: flex;margin: 30px;">

            <div class="card-img-top" style="height: 45%; white-space: nowrap;">
                <span class="helper"></span>
                <img src="{{item.image}}" style="margin: 0px; vertical-align: middle; display: inline-block;"
                    width="100%" alt="item.item.Name">
            </div>
            <div class="card-body">
                <h5 class="card-title" style="text-align: center;">{{item.item.Name}}</h5>
                <p class="card-description" style="height: 30%;">{{item.item.Description | Summery}}</p>
                <h5 class="card-text  price" style=" margin: 0px 0px 20px 0px ;">{{item.item.price | currency}}
                </h5>
                <ngb-rating [max]='5' [formControl]='item.control'>
                    <ng-template let-fill="fill">
                        <span class="star" [class.filled]="fill === 100">&#9733;</span>
                    </ng-template>
                </ngb-rating>
            </div>
            <button class="btn btn-primary mx-auto">add to cart</button>


        </div>
    </div>
</div>

您需要导入 FormModule 才能使其工作。

这个答案花了相当长的时间。我确实希望它有用(:

我创建了an issue修复文档。

关于angular - 页面初始化时触发 ngb-raring 上的rateChange,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67453351/

相关文章:

php - 通过使用 PHP 搜索特定记录的另一个列值来获取 MySql DB 表列值

Angular + ng-bootstrap - 模态 : window does not open

javascript - 如何在应用程序中为 Angular Forms 制作带有表单控件输入的通用组件

angular - 通用类型 'Observable<T>' 需要 1 个类型参数

data-binding - 变量更改时 Angular2 组件 View 不更新

javascript - Angular 单元测试: How to check if the spied upon method is getting the correct argument?

angular - 如何在 RxJS 主题中修改 map ?

typescript - 为什么 TypeScript 无法推断递归函数的类型

Angular2 - *ngIf 和 *ngFor 创建多个空元素

ng-bootstrap - NgbDropdown autoClose "outside"不起作用