angularangular-bootstrapangular-moduleangular-standalone-components

Angular 18 component is imported as non standalone component but fails to render


How to wire correctly NavbarComponent into the template of app component?

enter image description here

app.component.html

<app-navbar></app-navbar>
<router-outlet></router-outlet>

main.ts

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 {RouterModule} from '@angular/router';
import {AppComponent} from "./app/app.component";
import {appConfig} from "./app/app.config";
import {UserListComponent} from "./app/user-list/user-list.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 {NavbarComponent} from "./app/navbar/navbar.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
  ]
})
export class DemoMaterialModule {}

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

  ],
  providers: [provideHttpClient()]
})
export class AppModule {}

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

navbar.component.html

<mat-toolbar color="primary">
  <div class="container-fluid">
    <a class="navbar-brand" routerLink="/">Cars App</a>
    <button mat-icon-button (click)="toggleNavbar()">
      <mat-icon>menu</mat-icon>
    </button>
    <div class="collapse navbar-collapse nav nav-underline" [class.show]="isNavbarOpen" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item">
          <a class="nav-link" routerLink="/users">Users</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" routerLink="/cars">Cars</a>
        </li>
      </ul>
    </div>
  </div>
</mat-toolbar>

navbar.component.ts

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

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css'],
})
export class NavbarComponent {
  isNavbarOpen = false;
  toggleNavbar() {
    this.isNavbarOpen = !this.isNavbarOpen;
  }
}

app.component.ts

import { Component } from '@angular/core';
import {RouterOutlet} from '@angular/router';
import { AppModule } from '../main';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  standalone: true,
  imports: [AppModule, RouterOutlet]
})
export class AppComponent {
  title = 'webapp';
}

UPDATE:

When I made NavbarComponent standalone and made adjustments to wire it.

navbar.component.ts

import {Component} from '@angular/core';
import {MatToolbar} from "@angular/material/toolbar";
import {MatIcon} from "@angular/material/icon";

@Component({
  selector: 'app-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.css'],
  standalone: true,

  imports: [
    MatToolbar,
    MatIcon
  ]
})
export class NavbarComponent {
  isNavbarOpen = false;
  toggleNavbar() {
    this.isNavbarOpen = !this.isNavbarOpen;
  }
}

It compiles but the browser has the same error enter image description here

Code:

https://github.com/mr-olufsen/webapp

UPDATE 2:

The solution where NavbarComponent is integrated and rendered correct is here. Code. Although the table sorting is not working at the moment


Solution

  • The App was converted to standalone. Below were the steps followed.

    Created App Module and bootstrapped it

    @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));
    

    Removed all standalone components and added them to the app component (to have a general style across the app (modular) ).

    Github Repo


    Only environment providers should be added inside the second argument of bootstrap application.

    bootstrapApplication(AppComponent, { providers: [provideHttpClient(), provideRouter(routes), ] })
      .catch((err) => console.error(err));
    

    Then just import the modules into the standalone components, for the component to use them, just note: Only exported members can be used in the component.

    First we can convert navbar to standalone.

    import {Component} from '@angular/core';
    
    @Component({
      selector: 'app-navbar',
      templateUrl: './navbar.component.html',
      styleUrls: ['./navbar.component.css'],
      standalone: true,
    
    })
    export class NavbarComponent {
      isNavbarOpen = false;
      toggleNavbar() {
        this.isNavbarOpen = !this.isNavbarOpen;
      }
    }
    

    Then use it in app component.

    app.component.ts

    import { Component } from '@angular/core';
    import {RouterOutlet} from '@angular/router';
    import {NavbarComponent} from './src/navbar';
    import { AppModule } from '../main';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      standalone: true,
      imports: [AppModule, RouterOutlet, NavbarComponent]
    })
    export class AppComponent {
      title = 'webapp';
    }
    

    When working with standalone the below modules are not needed.

    BrowserModule,
    BrowserAnimationsModule,
    RouterModule.forRoot(routes),