Ionic3自定义Loading组件无法在页面模板中注入的问题求助
Hey there, let's sort out this Loading component issue you're facing in Ionic. It sounds like you've taken the first step by adding it to app.module.ts, but there are a few common pitfalls that might be stopping you from using it in your page templates. Let's break this down:
First: Correct Your AppModule Setup
First off, you mentioned adding the component to both declarations and providers arrays—that's a mistake. The providers array is for injectable services (marked with @Injectable()), not components. Components only belong in the declarations array, and if you want to use them across multiple pages/modules, you need to export them too.
Here's how your app.module.ts should look (adjust the component path to match yours):
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { IonicModule } from '@ionic/angular'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { LoaderComponent } from './components/loader/loader.component'; // Your component path @NgModule({ declarations: [ AppComponent, LoaderComponent // Only here for components ], imports: [ BrowserModule, IonicModule.forRoot(), AppRoutingModule ], exports: [ LoaderComponent // Export so other modules can access it ], bootstrap: [AppComponent] // Remove LoaderComponent from providers entirely! }) export class AppModule {}
Second: Use the Component in Your Page Template
Once your module is set up correctly, you can use the component directly in your page's HTML using its selector (the selector property from your component's @Component() decorator). For example, if your component's selector is app-loader, add this to your page template:
<ion-content class="ion-padding"> <!-- Your page content here --> <!-- Show loader when fetching data --> <app-loader *ngIf="isLoadingData"></app-loader> </ion-content>
Then in your page's TypeScript file, control the loader's visibility with a boolean flag:
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { isLoadingData = false; constructor(private http: HttpClient) {} fetchServerData() { this.isLoadingData = true; this.http.get('https://your-api-url.com/data').subscribe({ next: (response) => { // Handle your data here this.isLoadingData = false; }, error: (err) => { // Handle errors console.error(err); this.isLoadingData = false; } }); } }
Bonus: Make It a Reusable Service (For Easier Control)
If you want to call the loader from any component without adding the tag to every template, turn it into a service that dynamically injects the loader into the DOM. Here's how:
1. Create a Loader Service
import { Injectable, ComponentFactoryResolver, ApplicationRef, Injector } from '@angular/core'; import { LoaderComponent } from './components/loader/loader.component'; @Injectable({ providedIn: 'root' }) export class LoaderService { private loaderRef: any; constructor( private componentFactoryResolver: ComponentFactoryResolver, private appRef: ApplicationRef, private injector: Injector ) {} show() { // Create the loader component instance const factory = this.componentFactoryResolver.resolveComponentFactory(LoaderComponent); this.loaderRef = factory.create(this.injector); // Attach it to the app's root view this.appRef.attachView(this.loaderRef.hostView); // Add the component to the DOM const domElement = (this.loaderRef.hostView as any).rootNodes[0]; document.body.appendChild(domElement); } hide() { // Clean up the component this.appRef.detachView(this.loaderRef.hostView); this.loaderRef.destroy(); } }
2. Use the Service in Your Page
import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { LoaderService } from '../services/loader.service'; @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { constructor( private http: HttpClient, private loaderService: LoaderService // Inject the service ) {} fetchServerData() { this.loaderService.show(); this.http.get('https://your-api-url.com/data').subscribe({ next: (response) => { // Handle data this.loaderService.hide(); }, error: (err) => { console.error(err); this.loaderService.hide(); } }); } }
Key Takeaways to Avoid Future Issues
- Components go in
declarationsonly: Never add a component toproviders—that's for services. - Export components for cross-module use: If your pages are in feature modules, export the loader from AppModule (or create a shared module for reusable components).
- Template usage vs. injection: Components are used via their selector in templates; services are injected into constructors.
内容的提问来源于stack exchange,提问作者Sagar Khan

