如何在 *ngIf 的 else 部分指向其他组件

How to point other components in the else part of *ngIf

随着 的扩展,这是我需要在 *ngIf

的其他部分使用模板的另一种情况

这是我当前的代码,我在每个页面上使用加载微调器直到 API 响应 returns

   <ng-container *ngIf="!isLoading; else spinner">
         <form [formGroup]="myForm" novalidate (ngSubmit)="submit()" >
            // form content 
         </form>
    </ng-container>
    <ng-template #spinner>
        <div class="fa-3x tc">
            <i class="fas fa-spinner fa-spin"></i>
        </div>
    </ng-template>

这样我们必须在每个页面上编写相同的 #spinner 组件,所以我创建了一个具有相同内容的组件。

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

@Component({
    selector: 'app-display-loading',
    styles: [`.load__spinner { color: black; text-align: center; font-size: 30px;}`],
    template: `
        <ng-template>
            <div class="load__spinner"> <i class="fas fa-spinner fa-spin"></i></div>
        </ng-template>
    `,
    preserveWhitespaces: true
})

export class DisplayLoadingComponent {
    constructor() {
        console.log('display loading called');
    }
}

现在我的问题是如何在 *ngIf

中使用这个 <app-display-loading> 组件

或者这可能不是正确的方法。请建议如何执行此操作。

您可以使用 ng-template 来做到这一点,例如:

<div *ngIf="test; else otherTest"></div>
<ng-template #otherTest>
  <app-display-loading></app-display-loading>
</ng-template>

更新: 如果您正在使用路由,那么这个示例对您很有用:

在您的 AppComponent 中,您可以订阅导航更改 当 NavigationStart 显示您的微调器时,当 NavigationEnd 隐藏微调器时。

AppModule:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { NavbarComponent } from './navigation/navbar/navbar';
import { HomeComponent } from './views/home/home';
import { CategoriesComponent } from './views/categories/categories';

const routes: Routes = [
  { path: '', redirectTo: '/home', pathMatch: 'full' },
  { path: 'home', component: HomeComponent },
  { path: 'categories', component: CategoriesComponent }
];


@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes)
  ],
  declarations: [
    AppComponent,
    NavbarComponent,
    HomeComponent,
    CategoriesComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

AppComponent:

import { Component } from '@angular/core';
import { Router, NavigationStart, Event, NavigationEnd } from '@angular/router';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html'
})


export class AppComponent {
  timeout;
  routerChanged = true;
  constructor(private router: Router) {
    router.events.subscribe((event: Event) => {

      if (event instanceof NavigationStart) {
        // Show spinner
        this.routerChanged = true;
      }

      if (event instanceof NavigationEnd) {
        // Hide spinner
        this.timeout = setTimeout(() => {
          clearTimeout(this.timeout);
          this.routerChanged = false;
        }, 1000);
      }
    });
  }
}

应用组件Html:

<app-navbar></app-navbar>
<router-outlet></router-outlet>
<div class="spinner" *ngIf="routerChanged"></div>

Here is a worked example:

And you don't need any more to repeat the same spinner html in all your pages.

我在整个项目中使用类似于 <app-display-loading> 的东西,我需要做的就是

<app-display-loading *ngIf="isLoading"></app-display-loading>

但是首先你需要在组件所在的模块中添加DisplayLoadingComponent class这样

exports = [DisplayLoadingComponent]
declarations = [DisplayLoadingComponent]
<ng-container *ngIf="!isLoading">
     <form [formGroup]="myForm" novalidate (ngSubmit)="submit()" >
        // form content 
     </form>
</ng-container>

<app-display-loading *ngIf="isLoading"></app-display-loading>

设置正在加载accordingly.and, 在 submit()

中设置防止默认值

您好,您可以使用 HTTP 拦截器在每个请求中显示微调框。

您可以检查this。可能对你有帮助。为了调节微调器,您可以使用公共服务中的变量。

或者您可以在更高级别上使用您的加载组件,通过 CSS 您可以在整个页面上显示加载,因此您不需要其他条件部分。

Angular 结构指令可以帮助我们在 ngIf 指令的 else 部分指向其他组件。

您需要做的就是创建补充内置 ngIf 指令的指令。

最终语法应如下所示:

<div *ngIf="model withLoading">
  Model
</div>

这只是糖:

<ng-template [ngIf]="model" [ngIfWithLoading]="null">
  <div>
      Model
  </div>
</ng-template>

这里是指令本身:

@Directive({
  selector: '[ngIfWithLoading]',
})
export class LoadingDirective {
  @Input() set ngIf(val: any) {
    if (!val) {
      const factory = this.resolver.resolveComponentFactory(LoadingComponent);
      this.vcRef.createComponent(factory)
    }
  };

  constructor(private vcRef: ViewContainerRef, private resolver: ComponentFactoryResolver) { }
}

因此,一旦模型为假,上面的指令就会放置您的 LoadingComponent 而不是模型模板。

不要忘记将 LoadingComponent 包含到 entryComponents 数组中

Ng-run Example

另见