首页 > 解决方案 > 使用惰性加载就地绑定 ngFor

问题描述

我得到不能绑定到'ngForOf',因为它不是'li'的已知属性。 错误。

但我无法用可用的答案解决它。一般来说,每个答案都说要在应用程序的主模块(app.module.ts)文件中导入BrowserModule ,并在子模块中导入CommonModule 。

我正在尝试使用延迟加载,我想知道这是由于我的组件结构而发生的吗?

在此处输入图像描述

price.component.html我使用时出现以下错误*ngFor

<ul>
    <li *ngFor="let book of booksList">{{ book.author }}</li>
</ul>

Can't bind to 'ngForOf' since it isn't a known property of 'li'.

应用程序模块

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CoreModule } from './core/core.module';

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    CoreModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

应用程序路由模块

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  { path: '', loadChildren: () => import('./landing/landing.module').then(m => m.LandingModule) },
  { path: 'books', loadChildren: () => import('./books/books.module').then(m => m.BooksModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

书籍模块

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { BooksRoutingModule } from './books-routing.module';


@NgModule({
  declarations: [],
  imports: [
    CommonModule,
    BooksRoutingModule
  ]
})
export class BooksModule { }

书籍-routing.module

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AuthorsComponent } from './authors/authors.component';
import { PriceComponent } from './price/price.component';
import { CommonModule } from '@angular/common';

const routes: Routes = [
  { path: '', component: PriceComponent },
  { path: '/authors', component: AuthorsComponent }
];

@NgModule({
  imports: [RouterModule.forChild(routes), CommonModule],
  exports: [RouterModule],
  declarations: [AuthorsComponent, PriceComponent]
})
export class BooksRoutingModule { }

编辑

价格成分

import { Component, OnInit } from '@angular/core';
import { BookInfoService } from '../../book-info.service';

@Component({
  selector: 'app-price',
  templateUrl: './price.component.html',
  styleUrls: ['./price.component.scss']
})
export class PriceComponent implements OnInit {

  booksList={};
  constructor( private httpBooks: BookInfoService ) { }

  ngOnInit(): void {
    this.httpBooks.getBookDetails().subscribe( (result) => {
      this.booksList = result;
      console.log('book list ---> ' + this.booksList);
    })
  }
}

价格页面中的控制台

在此处输入图像描述

标签: angulartypescript

解决方案


@NgModule({
  imports: [RouterModule.forChild(routes), CommonModule],
  exports: [RouterModule],
  declarations: [AuthorsComponent, PriceComponent] // <-- remove, not declaration here, not nice
})
export class BooksRoutingModule { }
@NgModule({
  declarations: [AuthorsComponent, PriceComponent], // <-- put here. :)
  imports: [
    CommonModule,
    BooksRoutingModule
  ]
})
export class BooksModule { }

您还没有与我们分享您的 PriceComponent ... 所以..

@Component(...)
export class PriceComponent {
    bookList = [];
}
<ul>
    <li *ngFor="let book of booksList">{{ book.author }}</li>
</ul>

侧节点:

const routes: Routes = [
  { path: '', component: PriceComponent },
  { path: '/authors', component: AuthorsComponent }
];

@NgModule({
  declarations: [AuthorsComponent, PriceComponent],
  imports: [
    CommonModule,
    BooksRoutingModule,
    RouterModule.forChild(routes) // <-- work
  ]
})
export class BooksModule { }

更新1:

  • 使用:解析,您的组件将由有效数据启动。因此 Angular 将首先尝试解析数据,下一步是使用已解析数据加载组件。
// response model. (not required. If it not define set "Resolve<any>")
interface BookDetailsModel {
  id: number;
  book: string;
  author: string;
}; 

// https://angular.io/api/router/Resolve
@Injectable()
export class BookDetailsResolve implement Resolve<BookDetailsModel> {
  
  constructor(private httpBooks: BookInfoService ) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<BookDetailsModel> | Promise<BookDetailsModel> | BookDetailsModel {
    return this.httpBooks.getBookDetails(); // use error handler!
  }
}
const routes: Routes = [
  { path: '/authors', component: AuthorsComponent},
  { 
    path: '', 
    component: PriceComponent, 
    resolve: { details: BookDetailsResolve } // <-- add resolver
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule],

  // it is work, but I recommend add providers to normal module, just I dont want copy more code. :) 
  providers: [BookDetailsResolve]  // if not root provider, have to add to any parent or local module.
})
export class BooksRoutingModule { }
@Component({
  selector: 'app-price',
  templateUrl: './price.component.html',
  styleUrls: ['./price.component.scss']
})
export class PriceComponent implements OnInit {

  // typed attribute help your IDE. :)
  booksList: BookDetailsModel[] = []; // you can not foreach object! So I set to array.
  constructor(private route: ActivatedRoute) { }

  ngOnInit(): void {
    this.booksList = this.route.snapshot.data.details; // resolve key name will data.KEY. It will normal type, not Observable.
  }
}

推荐阅读