Angular 角虫。ngif在一种方法中不起作用
我的程序中出现了一个奇怪的bug,使得*ngIf停止工作 我的方法:Angular 角虫。ngif在一种方法中不起作用,angular,angular-ng-if,Angular,Angular Ng If,我的程序中出现了一个奇怪的bug,使得*ngIf停止工作 我的方法: stripeSubmit(){ this.stripeCheckout = false; // removes the form this.isLoading = true; // shows a loading spinner ... this.api.chargeCard(charge).subscribe(res =>{ if
stripeSubmit(){
this.stripeCheckout = false; // removes the form
this.isLoading = true; // shows a loading spinner
...
this.api.chargeCard(charge).subscribe(res =>{
if(res === "Success"){
this.api.submitOrder(this.orderObj).subscribe(res =>{
this.isLoading = false; // not working
sessionStorage.clear();
this.router.navigate(['/thank-you']) // is working but still displays /cart on top
});
}else {
console.log("ELSE condition"); // works
alert(res); // works
this.stripeFailBoolean = true; // doesn't work
this.stripeCheckout = true; // doesn't work
this.isLoading = false; // doesn't work
console.log(this.isLoading); // logs "false"
}
})
}
});
}
HTML:
。。。
你的车
...
出现问题,请重试
信用卡
到期月份
到期年
CVC
提交
正如上面注释掉的部分所示,当我单击submit时,表单将消失,微调器将启动。如果chargeCard方法成功,h1和加载微调器将保留,并且“/thank-you”的内容将显示在其下方(URL显示“/thank-you”)
如果该方法未通过if语句,则警报和日志将起作用,但3个布尔值均不起作用,微调器将无限期运行
我试着把我所有的布尔人都放在一个ngDoCheck上,但那根本没用
有人知道为什么我的布尔函数会起作用,除非在这个方法中?
谢谢
*****编辑:
如果愿意,您可以自己复制错误:
在船底租一艘船,然后去购物车
如果交易成功,请使用信用卡:
4242 4242 4242 4242
12/2024 123
如果资金不足,请使用信用卡:
4000 0000 0000 9995
12/2024 123
代码在
***********编辑2
以下是Stackblitz的代码:
Cart组件给我带来了麻烦,因为它是一个3ed party工具,并且似乎没有与Angular集成(当你在访问Stripe对象之前将窗口
投射到任何对象时,在回购协议中在线判断),我想说,这种意外行为是由在外部运行代码引起的
简单地说,如果您的代码调用某些代码作为某个外部代码的回调,Angular可能不知道代码已运行。这意味着Angular不知道某些值已更改->它不会触发更改检测->它没有正确刷新页面
导航为什么起作用?因为createToken
的回调中的代码导航到https://www.howlingwolfe.com/thank-you
。当URL更改时,将使用匹配组件。Angular不会更新视图,但会在URL更改时加载新组件
为什么console.log(this.isLoading)代码>正在工作吗?担心变量值的更新不是Angular的一部分。Angular不知道您更改了值,但在代码中您肯定更改了值,因此console.log
将打印正确的值。它将被更改,但如果在区域外执行,Angular将不会做任何事情
现在如何解决它:将NgZone
注入构造函数,并将整个代码(从第行开始)包装到中。\NgZone.run()
。您可以按照文档中提供的步骤进行操作
另一个问题可能是您正在订阅。我这里没有支持我的文档。主要原因是在订阅中从内部订阅取消订阅变得很棘手(公平地说,您至少应该为每个订阅使用takeUntil(unsubscribe$)
(因此…管道(takeUntil(this.unsubscribe$))。订阅(…)
)
下一步将是不进行内部订阅——这是更高的可观察性发挥作用的时候
举个例子,你应该避免这样做:
this.api.chargeCard(charge).subscribe(res1 => {
if (res1 === "Success") {
this.api.submitOrder(this.orderObj).subscribe(res2 => {...})
}
})
this.api.chargeCard(charge).pipe(
switchMap((res1: string) => res1 === "Success"
? this.api.submitOrder(this.orderObj).pipe(tap(/* do Your code here, clear and navigate*/))
: of(res1).pipe(tap(/* do Your code here on failure))),
finalize(() => this.isLoading = false),
takeUntil(this.unsubscribe$)
).subscribe()
这样做:
this.api.chargeCard(charge).subscribe(res1 => {
if (res1 === "Success") {
this.api.submitOrder(this.orderObj).subscribe(res2 => {...})
}
})
this.api.chargeCard(charge).pipe(
switchMap((res1: string) => res1 === "Success"
? this.api.submitOrder(this.orderObj).pipe(tap(/* do Your code here, clear and navigate*/))
: of(res1).pipe(tap(/* do Your code here on failure))),
finalize(() => this.isLoading = false),
takeUntil(this.unsubscribe$)
).subscribe()
非常感谢@Eatos!!NgZone绝对是一个不错的选择。以下是新的工作方法:
stripeSubmit(){
this.stripeCheckout = false;
this.isLoading = true;
this.stripeFailBoolean = false;
(<any>window).Stripe.card.createToken({
number: this.cardNumber,
exp_month: this.expMonth,
exp_year: this.expYear,
cvc: this.cvc
}, (status: number, response: any) => {
this.ngZone.run(() => {
if (status === 200) {
let charge: Charge = {
token: response.id,
price: this.total
}
// this.chargeCard(token);
this.api.chargeCard(charge).pipe(takeUntil(this.unsubscibe), tap(()=>{
console.log('inside of charge card tap');
}), switchMap((res: any)=>{
if(res === "Success"){
return this.api.submitOrder(this.orderObj).pipe(tap(()=>{
this.isLoading = false;
sessionStorage.clear();
this.router.navigate(['/thank-you'])
}))
} else {
return of(res).pipe(tap(()=>{
this.stripeFailText = res;
this.stripeFailBoolean = true;
this.stripeCheckout = true;
this.isLoading = false;
}))
}
})).subscribe();
}else {
console.log(response.error.message);
}
console.log('ngZone leave');
})
});
}
ngOnDestroy(){
this.unsubscibe.next();
this.unsubscibe.complete();
}
stripeSubmit(){
this.stripeCheckout=false;
this.isLoading=true;
this.stripeFailBoolean=false;
(窗口).Stripe.card.createToken({
号码:这个。卡号,
exp_month:this.expMonth,
exp_year:this.expYear,
这个
},(状态:编号,响应:任意)=>{
此.ngZone.run(()=>{
如果(状态===200){
充电:充电={
令牌:response.id,
价格:这个
}
//这是一张充值卡(代币);
this.api.chargeCard(charge).pipe(takeUntil(this.unsubsibe)),点击(()=>{
console.log('收费卡抽头内部');
}),switchMap((res:any)=>{
如果(res==“成功”){
返回this.api.submitor(this.orderObj.pipe)(点击(()=>{
this.isLoading=false;
sessionStorage.clear();
这个.router.navigate(['/thank-you'])
}))
}否则{
返回(res).管道(分接头(()=>{
this.stripeFailText=res;
this.stripeFailBoolean=true;
this.stripeCheckout=true;
this.isLoading=false;
}))
}
})).subscribe();
}否则{
console.log(response.error.message);
}
控制台日志('ngZone leave');
})
});
}
恩贡德斯特罗(){
this.unsubsibe.next();
this.unsubsibe.complete();
}
您可以创建一个更好地说明问题的方法吗?您也可以尝试使用我添加的live站点重新创建它,以便可以复制错误。stackblitz似乎无法正常工作,但我会继续尝试,非常感谢您的深思熟虑的回复!不幸的是,我在测试应用程序时仍然得到相同的行为n、 也许我没有使用tap对吗?我已经尝试了tap(()=>{/*mycode*/})
和tap({complete:()=>{/*mycode*/}}})
但是两者都给了我相同的结果。在tap()
内部的代码应该是什么样子?谢谢!我没有