为什么 Ionic-checkbox 在 Android 上并不总是刷新视图?

问题描述 投票:0回答:1

我正在使用带有独立模块和电容器的 Ionic 编写一个混合应用程序(请注意,我是个新手,所以并不是一切都完美)。我遇到了一个复选框问题,在浏览器中测试时不会出现该问题,但在真实的 Android 设备上却会出现该问题。

背景和代码

我有一个名为“new-visit”的页面组件,它允许创建新的医疗访问或更新现有的医疗访问。根据 url 参数,我可以创建一个具有默认值的表单,也可以使用现有访问中的数据填充它。

export class NewVisitPage implements OnInit {

  editMode: boolean = false;
  private existingVisit: VisitModel | undefined = undefined;
  private customers: CustomerDetails[] = [];
  public selectedCustomer: CustomerDetails | null = null;
  public customerSearchField: FormControl;
  public allowCustomerChange: boolean = true;

  constructor(
    private formBuilder: FormBuilder,
    private visitService: VisitsService,
    private route: ActivatedRoute,
    private customersService: CustomersService,
    private navCtrl: NavController,
    private toastCtrl: ToastController,
    private menuCtrl: MenuController) {
    this.customerSearchField = new FormControl('');
  }

  visitDataForm: FormGroup = this.formBuilder.group({
    customerId: ['', Validators.required],
    medicines: '',
    description: '',
    date: [moment().format('YYYY-MM-DD'), Validators.required],
    amount: 0,
    hasDebt: false,
    debtAmount: 0,
    debtPaidAmount: 0
  })

  ngOnInit() {
    addIcons(icons);

    this.visitDataForm.reset();

    this.route.queryParamMap.subscribe(params => {
      const customerId = params.get('customerId');
      if (customerId) {
        this.selectedCustomer = this.customersService.getCustomerById(customerId);
        this.customerId?.setValue(customerId);
        this.allowCustomerChange = false;
      }
    })

    this.route.paramMap.subscribe(params => {
      let date = params.get('date');
      if (date) {
        this.visitDataForm.get('date')!.setValue(date)
      }

      let id = params.get('id');
      if (id) {
        this.editMode = true;
        this.existingVisit = this.visitService.getById(id);
        if (!this.existingVisit)
          throw 'visit not found';

        this.visitDataForm.get('customerId')?.setValue(this.existingVisit.customerDetails.id);
        this.visitDataForm.get('medicines')?.setValue(this.existingVisit.medicines);
        this.visitDataForm.get('description')?.setValue(this.existingVisit.description);
        this.visitDataForm.get('date')?.setValue(moment(this.existingVisit.date).format('YYYY-MM-DD'));
        this.visitDataForm.get('amount')?.setValue(this.existingVisit.amount);
        this.visitDataForm.get('hasDebt')?.setValue(!!this.existingVisit.debt);
        this.visitDataForm.get('debtAmount')?.setValue(this.existingVisit.debt?.amount || 0);
        this.visitDataForm.get('debtPaidAmount')?.setValue(this.existingVisit.debt?.amountPaid || 0);

        this.selectedCustomer = this.customersService.getCustomerById(this.existingVisit.customerDetails.id);
      }
    });
  }

  get hasDebt() {
    return this.visitDataForm.get('hasDebt')!.value;
  }

  get customerId() {
    return this.visitDataForm.get('customerId')!;
  }

// ...

然后,在 UI 方面,在表单元素内,我有一个复选框,允许选择客户是否为整个访问付费或有一些债务。根据复选框的值,我要么显示用于编辑债务金额的文本框,要么不显示。

<ion-item lines="full">
  <ion-checkbox labelPlacement="end" formControlName="hasDebt">
    <div class="ion-text-wrap">Amount was not fully paid</div>
  </ion-checkbox>
</ion-item>

<ion-item *ngIf="hasDebt">
  <ion-label position="floating">Debt amount</ion-label>
  <ion-input type="number" step="0.01" min="0" formControlName="debtAmount"></ion-input>
</ion-item>
<ion-item *ngIf="hasDebt && editMode">
  <ion-label position="floating">Paid amount</ion-label>
  <ion-input type="number" step="0.01" min="0" formControlName="debtPaidAmount"></ion-input>
</ion-item>

问题

当我在浏览器中使用

ng serve
运行应用程序时,一切正常。当我将复选框标记为选中时,字段可见,否则不可见。

但是在 Android 上,它仅在创建新访问时有效。当我尝试编辑现有的一个时,它会随机停止工作 - 我可以更改复选框值,并且看到复选框本身的视觉效果,但“ngIf”部分在我最小化应用程序之前不起作用。似乎“ngIf”仅在最小化应用程序时才会触发。

android angular ionic-framework
1个回答
0
投票

这看起来像是角度变化检测问题,但可能还有另一个潜在问题。

1.尝试开启生产模式

当您运行

ng serve
时,应用程序很可能处于调试模式,因此对某些运行时错误更加宽容。您可以尝试通过
ng serve --configuration=production
在生产模式下运行。根据您的构建,构建模式正在使用生产模式。您可能会发现发生的任何潜在错误,并且可能会复制该错误。

2.手动检测复选框值变化

看看手动触发更改检测是否可以修复该问题。

    // add to constructor
    private changeDetector: ChangeDetectorRef


    // add inside your ngOnInit function
    this.visitDataForm.get('hasDebt').valueChanges.subscribe(()=> {
      this.changeDetector.detectChanges();
    })

3.改变检测策略

如果您的更改检测策略设置为 OnPush,组件中的 getter 可能无法按您的预期工作,将其设置回默认值应该可以修复它。

@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
...

4.修复底层检测问题

此吸气剂可能无法按预期工作。更改检测最适合原始值,而不是对象引用。在这种情况下,即使值已更改,Angular 也可能无法从对象的引用中跟踪它。

  get hasDebt() {
    return this.visitDataForm.get('hasDebt')!.value;
  }

例如,您可以创建自己的原语来代替此 getter

import {
  startWith,
} from 'rxjs';

hasDebt$ = this.visitDataForm.get('hasDebt').valueChanges.pipe(startWith(this.visitDataForm.get('hasDebt').value))
<ion-item *ngIf="hasDebt">

变成:

<ion-item *ngIf="hasDebt$ | async">

这样,您就可以保持变更检测的效率

© www.soinside.com 2019 - 2024. All rights reserved.