В своем приложении я загрузил внешнюю библиотеку «braintree.js» ... все работает правильно, но есть странное поведение, которое я не могу понять.

В моем шаблоне блок div загружается в зависимости от значения переменной (regStep): когда я вызываю внешнюю библиотеку, даже если значение regStep изменяется, шаблон не показывает изменения, если я прокомментирую вызов внешнюю библиотеку и измените значение regStep, шаблон изменится соответственно.

Я не скопировал весь код, но заверяю, что все необходимые переменные объявлены.

Я новичок в Angular, возможно, я что-то теряю, но я действительно не понимаю, в чем проблема.

Это задействованные файлы:

< Сильный > component.html

<div *ngIf="regservice.regStep == 1">
   <form (ngSubmit)="regservice.savePay();
   ...tags...
   </form>
</div>
<div *ngIf="regservice.regStep == 2">
   ...tags...
</div>

< Сильный > regservice.ts

declare var braintree: any;

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';

@Injectable({
   providedIn: 'root'
})

export class RegisterService {

  constructor(public router: Router, private http: HttpClient) {}
  public regStep = 1;

public savePay() : void {

let self = this;

let client = new braintree.api.Client({clientToken: this.bt_token});

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, function (err, nonce) {
  if (nonce) {
    console.log(nonce); 
    self.addPayment(nonce);
  }
});
//this.addPayment('fake-valid-nonce');
//If I uncomment the above line and comment all the others everything works perfectly
}

private addPayment(nonce) : void {  

 this.http.post(this.apiUrl+'/bt-add-payment-method/',
{
    payment_method_nonce: nonce,
    billing_address_id: this.business.braintree_customer.id,
    make_default: true

},
{
  headers:{
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + this.token['access_token']
  }}).subscribe( {
      next : response => { console.log('RESPONSE ADD PYMNT : ',response); },
      error: err => {this.handleErrors(err); },
      complete: () => { this.forward(); },
    }); 
 }

 private forward() {
  switch (this.regStep) {
     case 1 : {
        this.regStep_value = 'Step 2 of 5';
        this.regStep++;             
    }
    break;
  }
}

< Сильный > UPDATE

Даже используя:

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, (err, nonce) => {
    console.log(nonce); 
    this.addPayment(nonce);  
});

Проблема не устранена. Шаблон остается заблокированным для блока STEP == 1.

Если я не вызываю новое дерево мозгов и связанный с ним код, все работает.

В обоих случаях я вижу console.log RESPONSE ADD PYMNT, поэтому в обоих случаях вызывается функция AddPayment; в обоих случаях вызывается также функция forward.

В обоих случаях я вижу, что regStep равен 2, но

  1. если я вызвал Braintree, шаблон останется заблокированным до предыдущего состояния.

  2. если я не вызвал braintree, шаблон изменится, как только изменится regStep.

1
Bux 22 Окт 2018 в 17:30

2 ответа

Лучший ответ

Проблема была связана с выходом асинхронной функции из зоны Angular.

Это решит проблему:

client.tokenizeCard({
  number: '',
  expirationDate: '',
  cvv : ''
}, (err, nonce) => {
  this.zone.run(() => { //<=== added
    console.log(nonce); 
    this.addPayment(nonce);  
  })
});

Логически вам нужно импортировать NgZone

import { NgZone } from '@angular/core';

export class RegisterService {

  constructor(private zone:NgZone ) {}
}
1
Bux 24 Окт 2018 в 14:00

Если вы хотите использовать переменные / методы компонента внутри обратного вызова, лучше использовать лямбда-функцию (=>) вместо использования буквальных или анонимных функций. В вашем случае вы можете использовать следующее:

(err, nonce) => {   
   if (nonce) {
       console.log(nonce); 
       this.addPayment(nonce);   
    }
}
0
alokstar 22 Окт 2018 в 14:39
52931791