Ошибка типа: невозможно прочитать свойства неопределенного значения (чтение «ɵcmp») в Angular 18

Я пытаюсь заставить сортировку таблицы работать для /users, которая определена в UserListComponent. Функциональность сортировки была нарушена из-за введения NavbarComponent.

Я устал по возможности переключаться на автономные компоненты, как предложено в этом ответе. Я новичок в Angular, и, насколько я понимаю, @NgModule в DemoMaterialModule (main.ts) весьма полезен, поскольку мне не нужно импортировать каждый модуль материала в каждом компоненте.

Angular 18 продвигает автономный подход, поэтому, возможно, стоит пойти по этому пути.

Является ли это лучшим вариантом для моего варианта использования? Не лучше ли полностью перейти от моего гибридного подхода (автономный + модульный) к автономному?

Как заставить это работать?

GitHub

ОБНОВЛЯТЬ:

Сортировка не работает. Обновлен код . Добавлены демонстрационные данные для легкого воспроизведения проблемы сортировки.

ОБНОВЛЕНИЕ 2:

Наконец-то всё заработало: Коммит GitHub

надеюсь это поможет!

Naren Murali 26.06.2024 08:13

Спасибо за помощь! Код компилируется. Ошибка исчезла. Проблема в том, что сортировка не работает...

J.Olufsen 26.06.2024 09:33

Ваши ответы были весьма полезны. Большое спасибо! Я принял ответы. Дело в том, что когда я пытаюсь починить одну деталь, другая ломается. (Может быть немного не по теме: external-preview.redd.it/…)

J.Olufsen 26.06.2024 09:55

Я могу только указать решение, а не предоставить код без ошибок, это зависит от вас!

Naren Murali 26.06.2024 09:57
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
1
4
233
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во время преобразования автономного стиля в модульный мы используем в маршрутизации компоненты, которые не импортируются в AppModule, что чаще всего и вызывает проблему.

Я преобразовал все приложение в автономное, как было указано в предыдущем вопросе.

import {CdkTableModule} from '@angular/cdk/table';
import {NgModule} from '@angular/core';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {bootstrapApplication, BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {MatAutocompleteModule} from "@angular/material/autocomplete";
import {MatButtonModule} from "@angular/material/button";
import {MatButtonToggleModule} from "@angular/material/button-toggle";
import {MatCardModule} from "@angular/material/card";
import {MatCheckboxModule} from "@angular/material/checkbox";
import {MatChipsModule} from "@angular/material/chips";
import {MatStepperModule} from "@angular/material/stepper";
import {MatDatepickerModule} from "@angular/material/datepicker";
import {MatDialogModule} from "@angular/material/dialog";
import {MatDividerModule} from "@angular/material/divider";
import {MatExpansionModule} from "@angular/material/expansion";
import {MatGridListModule} from "@angular/material/grid-list";
import {MatIconModule} from "@angular/material/icon";
import {MatInputModule} from "@angular/material/input";
import {MatListModule} from "@angular/material/list";
import {MatMenuModule} from "@angular/material/menu";
import {MatNativeDateModule, MatRippleModule} from "@angular/material/core";
import {MatPaginatorModule} from "@angular/material/paginator";
import {MatProgressBarModule} from "@angular/material/progress-bar";
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
import {MatRadioModule} from "@angular/material/radio";
import {MatSelectModule} from "@angular/material/select";
import {MatSidenavModule} from "@angular/material/sidenav";
import {MatSliderModule} from "@angular/material/slider";
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
import {MatSnackBarModule} from "@angular/material/snack-bar";
import {MatTabsModule} from "@angular/material/tabs";
import {MatToolbarModule} from "@angular/material/toolbar";
import {MatTooltipModule} from "@angular/material/tooltip";
import {MatTableModule} from '@angular/material/table';
import {provideHttpClient} from "@angular/common/http";
import {provideRouter, RouterModule} from '@angular/router';
import {AppComponent} from "./app/app.component";
import {CarListComponent} from "./app/cars-list/car-list.component";
import {CarComponent} from "./app/car/car.component";
import { routes } from './app/app.routes';
import {MatSortModule} from "@angular/material/sort";
import {UserCarsComponent} from "./app/user-cars/user-cars.component";
import {UserComponent} from "./app/user/user.component";
import {CommonModule} from "@angular/common";
import {MatFormFieldModule} from "@angular/material/form-field";
import { NavbarComponent } from './app/navbar/navbar.component';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UserListComponent } from './app/user-list/user-list.component';


@NgModule({
  exports: [
    CdkTableModule,
    MatAutocompleteModule,
    MatButtonModule,
    MatButtonToggleModule,
    MatCardModule,
    MatCheckboxModule,
    MatChipsModule,
    MatStepperModule,
    MatDatepickerModule,
    MatDialogModule,
    MatDividerModule,
    MatExpansionModule,
    MatGridListModule,
    MatIconModule,
    MatInputModule,
    MatListModule,
    MatMenuModule,
    MatNativeDateModule,
    MatPaginatorModule,
    MatProgressBarModule,
    MatProgressSpinnerModule,
    MatRadioModule,
    MatRippleModule,
    MatSelectModule,
    MatSidenavModule,
    MatSliderModule,
    MatSlideToggleModule,
    MatSnackBarModule,
    MatTableModule,
    MatTabsModule,
    MatToolbarModule,
    MatTooltipModule,
    MatDialogModule,
    MatGridListModule,
    MatSortModule,
    MatFormFieldModule
  ]
})
export class DemoMaterialModule {}

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    DemoMaterialModule,
    MatNativeDateModule,
    ReactiveFormsModule,
    RouterModule.forRoot(routes),
    RouterModule,
    CommonModule
  ],
  declarations: [
    AppComponent,
    NavbarComponent,
    UserListComponent,
    UserComponent,
    CarListComponent,
    CarComponent,
    UserCarsComponent,
  ],
  bootstrap: [AppComponent],
  exports: [
  ],
  providers: [provideHttpClient()]
})
export class AppModule {}


platformBrowserDynamic().bootstrapModule(AppModule, {
  ngZoneEventCoalescing: true
})
  .catch(err => console.error(err));

Ниже приведены изменения кода для исправления сортировки. Если у вас возникнут сомнения, дайте мне знать.

import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { MatSort, Sort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Car } from "../models/car.model";
import { ActivatedRoute, Router } from '@angular/router';
import { CarService } from '../services/car.service';
import { FormControl } from "@angular/forms";
import { debounceTime, takeUntil } from "rxjs/operators";
import { Subject } from 'rxjs';

function compare(a: number | string, b: number | string, isAsc: boolean) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

@Component({
  selector: 'app-cars',
  templateUrl: './car-list.component.html',
  styleUrls: ['./car-list.component.css']
})
export class CarListComponent implements OnInit, AfterViewInit {
  displayedColumns: string[] = ['id', 'make', 'model', 'numberplate'];
  dataSource: MatTableDataSource<Car>;
  cars: Car[] = [];
  filterControl: FormControl = new FormControl('');
  private ngUnsubscribe = new Subject<void>();

  @ViewChild(MatSort) sort!: MatSort;

  constructor(private carService: CarService,
              private route: ActivatedRoute,
              private router: Router) {
    this.dataSource = new MatTableDataSource<Car>();
  }

  ngOnInit() {
    this.initializeTable();
  }

  ngAfterViewInit() {
    this.route.queryParams.pipe(takeUntil(this.ngUnsubscribe)).subscribe(params => {
      const { find } = params;
      this.filterControl.setValue(find || '');
      this.applyFilter(find || '');
    });
  }

  initializeTable() {
    // Fetch cars from service
    // this.carService.getCars().subscribe((data: Car[]) => {
    //   this.cars = data;
    //   this.dataSource.data = this.cars;
    // });
    // fake API call
      this.cars = [
        {
          id: 1,
make: 'car1',
model: 'asdf1',
numberplate: '12344',
        },
        {
          id: 2,
make: 'car2',
model: 'asdf2',
numberplate: 'h4r5ty',
        },
        {
          id: 1,
make: 'car33',
model: 'asdf33',
numberplate: 'zxcvfbdf',
        },
        {
          id: 1,
make: 'car45',
model: 'asdf45',
numberplate: 'asdfae',
        }
      ];
      this.dataSource.data = this.cars;

    // Set filter predicate
    this.dataSource.filterPredicate = (data, filter: string): boolean => {
      return data.make.toLowerCase().includes(filter) || data.model.toLowerCase().includes(filter) || data.numberplate.toLowerCase().includes(filter);
    };

    // Subscribe to changes in the filter control with debounce
    this.filterControl.valueChanges.pipe(
      debounceTime(300),
      takeUntil(this.ngUnsubscribe)
    ).subscribe(value => {
      this.applyFilter(value);
    });
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim().toLowerCase();
    this.dataSource.filter = filterValue;
    // Update the URL with the new filter value or remove the parameter if the filter is empty
    this.router.navigate([], {
      relativeTo: this.route,
      queryParams: filterValue ? { find: filterValue } : {},
      queryParamsHandling: filterValue ? 'merge' : ''
    });
  }

  applySort(sortState: Sort) {
    const data = this.cars.slice();
    if (!sortState.active || sortState.direction === '') {
      this.dataSource.data = data;
      return;
    }

    this.dataSource.data = data.sort((a, b) => {
      const isAsc = sortState.direction === 'asc';
      switch (sortState.active) {
        case 'id':
          return compare(a.id, b.id, isAsc);
        case 'make':
          return compare(a.make, b.make, isAsc);
        case 'model':
          return compare(a.model, b.model, isAsc);
        case 'numberplate':
          return compare(a.numberplate, b.numberplate, isAsc);
        default:
          return 0;
      }
    });
    const sortField = sortState.active;
    const sortDirection = sortState.direction as 'asc' | 'desc';

    // Update the URL with the new sort value
    this.router.navigate([], {
      relativeTo: this.route,
      queryParams: { sort: `${sortField}:${sortDirection}` },
      queryParamsHandling: 'merge'
    });
  }

  navigateToCarDetail(car: Car): void {
    this.router.navigate(['/cars', car.id]);
  }
}

Репозиторий Github

@J.Olufsen обновил мой ответ!

Naren Murali 26.06.2024 10:30

Сортировка работает. Большое спасибо!

J.Olufsen 26.06.2024 10:57

У вас такие же ошибки в консоли браузера? ОШИБКА TypeError: this.sort не определен.

J.Olufsen 26.06.2024 10:58

@J.Olufsen закомментируйте эту строку, она не нужна

Naren Murali 26.06.2024 10:59

Другие вопросы по теме