简体   繁体   English

Javascript / Angular - html 在渲染代码之前显示

[英]Javascript / Angular - html displays before rendering code

I have a function to get rates from products, so lets say I have one product with two rates.我有一个 function 可以从产品中获取费率,所以可以说我有一个产品有两个费率。 So my product has two rates.所以我的产品有两种费率。 Then, when I get those rates I must get the prices attached to my product.然后,当我得到这些费率时,我必须得到我的产品的附加价格。 So for each rate I have to look for its prices.所以对于每个费率,我都必须寻找它的价格。

The next code below explains this:下面的下一个代码解释了这一点:

this.loadProductInfo = true; // bool to load data in my form

// First of all, I get rates from API
// const rates = this._http....
// Now, for each rate I must search If my product/products have a price:

this.rates.forEach((rate, index, arr) => {
   this._glbGetPricesForProduct.getPrice(params).subscribe(response => {
      if (!arr[index + 1]) {
        this.initForm();
        this.loadProductInfo = false;
      } 
   })
});

The variable loadProductInfo it loads content in my form, so in my html I have:变量 loadProductInfo 它在我的表单中加载内容,所以在我的 html 中我有:

<form *ngIf="!loadProductInfo"></form>

But form it still give me error: could not find control name.但它仍然给我错误:找不到控件名称。

But if I do this instead, it works correctlly:但如果我这样做,它会正常工作:

setTimeout(() => {
    this.initForm();
    this.loadProductInfo = false;
}, 2000);

So what I want its to say my form to wait until I have all code loaded and then after it, load its contents.所以我想让它说我的表单要等到我加载了所有代码,然后再加载它的内容。 But instead it cant find the control because it loads before code.但是它找不到控件,因为它在代码之前加载。 Any help I really appreciate it.任何帮助我真的很感激。

The main mistake I see there is that you are looping over async data which may not be there when your code execute the for each loop (your rates).我看到的主要错误是您正在遍历异步数据,当您的代码执行 for each 循环(您的费率)时,这些数据可能不存在。
I would build an observable with your rates as a source:我将以您的费率作为来源构建一个可观察对象:

...
$rates: Observable<any> = this._http.get(...);
rates.pipe(
    mergeMap((rates) => {
        const priceByRates: Observable<any>[] = rates.map((rate, index, arr) => this._glbGetPricesForProduct.getPrice(params));
        return combineLatest(pricesByRates); // if getPrice complete right away, use forkJoin() instead
    })
).subscribe(res => {
    // No need to check for the last item, all rates have been checked for possible price
    this.initForm();
    this.loadProductInfo = false; 
});
...

This implementation should wait for your api calls to resolve before printing your form.此实现应在打印表单之前等待您的 api 调用解决。

Since you are hiding the entire form, it may be better to just move the API call into a resolver so that the page does not render until the data is ready.由于您隐藏了整个表单,因此最好将 API 调用移动到解析器中,以便在数据准备好之前不会呈现页面。

Here is a minimal StackBlitz showcasing this behavior: https://stackblitz.com/edit/angular-ivy-4beuww这是展示此行为的最小 StackBlitz: https://stackblitz.com/edit/angular-ivy-4beuww

Component零件

In your component, include an ActivatedRoute parameter via DI.在您的组件中,通过 DI 包含一个 ActivatedRoute 参数。

@Component(/*omitted for brevity*/)
export class MyComponent {
  constructor(private route: ActivatedRoute) {
    // note: 'data' is whatever you label your resolver prop in your routing setup
    route.data.subscribe(resolved => {
      if ("data" in resolved) this.resolveData = resolved["data"];
    });
  }
}

Route Setup路线设置

And in your router setup you would have the following:在您的路由器设置中,您将拥有以下内容:

const routes: Routes = [
  {
    path: 'my-route-path',
    component: MyComponent,
    resolve: {
      data: MyResolver
    }
  }
];

Resolver解析器

Finally, your resolver would make your API call utilizing your service:最后,您的解析器将使用您的服务拨打您的 API 电话:

@Injectable({providedIn: 'root'})
export class MyResolver() implements Resolve<T> {

  constructor(private service: MyService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | any {
    return this.service.myRequest();
  }
}

The final result will be that your view will not be rendered until your data is ready.最终结果将是在您的数据准备好之前不会呈现您的视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM