Avatar ·

Ошибка "Can't bind to 'ngFor' since it isn't a known native property" в Angular

Всем привет! Я новичок в Angular и TypeScript, пытаюсь освоить работу со списками. У меня есть простой компонент, который должен выводить список пользователей. Вот код моего компонента: ```typescript import { Component } from '@angular/core'; @Component({ selector: 'app-user-list', template: `

Список пользователей

  • {{ user.name }}
` }) export class UserListComponent { users = [ { name: 'Иван', age: 25 }, { name: 'Мария', age: 30 }, { name: 'Петр', age: 28 } ]; } ``` Но при запуске приложения я получаю ошибку в консоли браузера: ``` ERROR Error: Uncaught (in promise): Error: Template parse errors: Can't bind to 'ngFor' since it isn't a known native property ``` Я уже проверил, что импортировал BrowserModule в AppModule, но ошибка всё равно появляется. Что я делаю не так? Как правильно использовать *ngFor в Angular? Нужно ли что-то дополнительно импортировать или настраивать? Буду благодарен за подробное объяснение. <<>>

Проблема: отсутствие CommonModule в модуле компонента

Основная причина этой ошибки — Angular не может найти директиву *ngFor в текущем модуле. Хотя вы импортировали BrowserModule в корневой модуль, для использования *ngFor и других структурных директив (*ngIf, *ngSwitch) необходимо импортировать CommonModule в каждый модуль, где используются эти директивы.

CommonModule содержит все основные директивы Angular, включая NgFor, NgIf, NgSwitch, а также пайпы (DatePipe, UpperCasePipe и др.) и другие базовые возможности.

Решение: импортируйте CommonModule

Вам нужно добавить CommonModule в массив imports вашего модуля. Вот исправленный код:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { AppComponent } from './app.component';
import { UserListComponent } from './user-list.component';

@NgModule({
  declarations: [
    AppComponent,
    UserListComponent
  ],
  imports: [
    BrowserModule,
    CommonModule  // <-- Добавьте эту строку
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Если ваш компонент находится в отдельном модуле (например, UserModule), импортируйте CommonModule именно туда:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UserListComponent } from './user-list.component';

@NgModule({
  declarations: [UserListComponent],
  imports: [CommonModule],  // <-- Обязательно!
  exports: [UserListComponent]
})
export class UserModule { }

Почему это работает?

  • BrowserModule — экспортирует CommonModule, но только для корневого модуля приложения. Он предназначен для однократного импорта в AppModule.
  • CommonModule — это модуль, который содержит все основные директивы Angular. Его нужно импортировать в каждый функциональный модуль, где используются эти директивы.
  • Angular использует модульную систему: каждый модуль изолирован, и директивы из одного модуля не видны в другом без явного импорта.

Дополнительные советы

1. Проверьте версию Angular. В очень старых версиях (Angular 2 beta) *ngFor назывался *ng-for, но в современных версиях (2+) используется *ngFor.

2. Используйте трек-функцию для оптимизации производительности при работе с большими списками:

trackByUser(index: number, user: any): number {
  return user.id; // или любой уникальный идентификатор
}

И в шаблоне:

<li *ngFor="let user of users; trackBy: trackByUser">{{ user.name }}</li>

3. Помните о синтаксисе. Звёздочка (*) перед ngFor — это синтаксический сахар для использования шаблонов. Без неё нужно писать:

<ng-template ngFor let-user [ngForOf]="users">
  <li>{{ user.name }}</li>
</ng-template>

Но вариант со звёздочкой проще и читаемее.

После добавления CommonModule ошибка должна исчезнуть, и ваш список пользователей будет корректно отображаться.

<<>>

Альтернативный подход: использование standalone компонентов

Начиная с Angular 14, вы можете использовать standalone компоненты, которые не требуют объявления в модуле. Это упрощает структуру приложения и избавляет от необходимости импортировать CommonModule вручную.

Вот как переписать ваш компонент с использованием standalone подхода:

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

@Component({
  selector: 'app-user-list',
  standalone: true,  // <-- Указываем, что компонент standalone
  imports: [CommonModule],  // <-- Импортируем CommonModule напрямую
  template: `
    <div>
      <h2>Список пользователей</h2>
      <ul>
        <li *ngFor="let user of users">{{ user.name }}</li>
      </ul>
    </div>
  `
})
export class UserListComponent {
  users = [
    { name: 'Иван', age: 25 },
    { name: 'Мария', age: 30 },
    { name: 'Петр', age: 28 }
  ];
}

Теперь вам не нужно добавлять компонент в declarations или imports модуля. Просто импортируйте его туда, где используете:

import { bootstrapApplication } from '@angular/platform-browser';
import { UserListComponent } from './user-list.component';

bootstrapApplication(UserListComponent);

Этот подход особенно удобен для небольших приложений или при миграции с более старых версий Angular. Он делает код более модульным и уменьшает количество boilerplate кода.

Обратите внимание: если вы используете Angular 14 и выше, standalone компоненты — это рекомендуемый способ разработки новых приложений.