I am utilizing Swiper in several of my components, and I've encountered an issue when Angular routing changes especially routeParams eg. /route/:id – it doesn't function correctly. To address this, I implemented ngZone. This resolved the main Swiper functionality, but the thumbs Swiper is still behaving unexpectedly. I believe that rather than initializing twice, it would be more efficient to initialize once with both the main Swiper and thumb Swiper details. However, I am unsure about the syntax. Can someone please assist me with this?
Note: The objective is to ensure that Swiper works seamlessly when navigating between different routes.
html:
    <div>
    <swiper-container #swiper1 style="--swiper-navigation-color: #fff; --swiper-pagination-color: #fff" class="mySwiper"
        thumbs-swiper=".mySwiper2" navigation="true" init="false">
        <swiper-slide *ngFor="let slide of slides">
            <img [src]="slide.image" />
        </swiper-slide>
    </swiper-container>

    <swiper-container #swiper2 class="mySwiper2" space-between="10" slides-per-view="6" free-mode="true"
        watch-slides-progress="true" init="false">
        <swiper-slide *ngFor="let slide of slides">
            <img [src]="slide.image" />
        </swiper-slide>
    </swiper-container>
</div>

css:
swiper-slide {
  text-align: center;
  font-size: 18px;
  background: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  background-size: cover;
  background-position: center;
  img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
}

.mySwiper {
  height: 600px;
  width: 100%;
}

.mySwiper2 {
  // defines height and width of thumbs swiper
  height: 100px;
  width: 100%;
  box-sizing: border-box;
  padding: 10px 0;
  swiper-slide {
    opacity: 0.6; // this set default opacity to all slides
  }
  .swiper-slide-thumb-active {
    opacity: 1; // this reset the opacity one for the active slide
  }
}

ts
import { CommonModule } from '@angular/common';
import {
  Component,
  OnInit,
  CUSTOM_ELEMENTS_SCHEMA,
  ViewChild,
  ElementRef,
  AfterViewInit,
  NgZone,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-swiper-thumbs-vertical-dup-1',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './swiper-thumbs-vertical-dup-1.component.html',
  styleUrl: './swiper-thumbs-vertical-dup-1.component.scss',
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class SwiperThumbsVerticalDup1Component implements OnInit, AfterViewInit {
  @ViewChild('swiper1') swiper1!: ElementRef<any>;
  @ViewChild('swiper2') swiper2!: ElementRef<any>;

  slides: any[] = []

  constructor(private zone: NgZone, private route: ActivatedRoute) { }

  ngOnInit() {
    this.routeSub = this.route.params.subscribe(params => {
      const id = params['id'];
      if (id == 1) {
        this.slides = [
          { image: 'https://swiperjs.com/demos/images/nature-1.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-2.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-3.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-4.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-5.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-6.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-7.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-8.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-10.jpg' },
        ];
      } else {
        this.slides = [
          { image: 'https://swiperjs.com/demos/images/nature-6.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-7.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-8.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-10.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-1.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-2.jpg' },
          { image: 'https://swiperjs.com/demos/images/nature-3.jpg' },
        ];
      }
    });
  }

  ngAfterViewInit() {
    this.zone.runOutsideAngular(() => {
      const swiperParams = {
        breakpoints: {
          100: {
            slidesPerView: 3,
          },
          640: {
            slidesPerView: 5,
          },
          1024: {
            slidesPerView: 6,
          },
        },
      };

      const swiperParams1 = {
        spaceBetween: 10
      };

      Object.assign(this.swiper2.nativeElement, swiperParams1);
      this.swiper1.nativeElement.initialize();

      // now we need to assign all parameters to Swiper element
      Object.assign(this.swiper2.nativeElement, swiperParams);
      this.swiper2.nativeElement.initialize();
    });
  }
}


I am trying to implement a image-slider.
I have a image-slider componenent and a component in which i want to display the image slider
I'd like to automatically slide through the images.
image-slider-component.html:

    @if (indicatorsVisible) {

      @for(slide of slides; track $index; ){

      }

    }

    <button (click)="next()" class="nextButton">
      far
    </button>
    <button (click)="previous()" class="previousButton">
      back
    </button>

image-slider-component.ts
import { Component, Input, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-image-slider',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './image-slider.component.html',
  styleUrl: './image-slider.component.scss',
})
export class ImageSliderComponent implements OnInit{

  @Input() slides: any[] = [];
  @Input() indicatorsVisible = true;
  @Input() animationSpeed = 500;
  @Input() autoPlay = true;
  @Input() autoPlaySpeed = 3000;
  currentSlide = 0;
  hidden = false;

  next() {
    let currentSlide = (this.currentSlide + 1) % this.slides.length;
    this.jumpToSlide(currentSlide);
  }

  previous() {
    let currentSlide =
      (this.currentSlide - 1 + this.slides.length) % this.slides.length;
    this.jumpToSlide(currentSlide);
  }

  jumpToSlide(index: number) {
    this.hidden = true;
    setTimeout(() => {
      this.currentSlide = index;
      this.hidden = false;
    }, this.animationSpeed);
  }

  ngOnInit() {
    if (this.autoPlay) {
      setInterval(() => {
        this.next();
      }, this.autoPlaySpeed);
    }
  }

}

more.component.html (i'd like to display the img-slider here)

  <app-image-slider
    [indicatorsVisible]="false"
    [animationSpeed]="100"
    [slides]="slides"
    [autoPlay]="true"
    [autoPlaySpeed]="5"
  ></app-image-slider>

  <app-image-slider
    [indicatorsVisible]="true"
    [animationSpeed]="400"
    [slides]="slides"
    [autoPlay]="true"
    [autoPlaySpeed]="5"
  ></app-image-slider>

more.component.ts (here are the imgs that are used by the img-slider)
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterOutlet } from '@angular/router';
import { ImageSliderComponent } from '../about/components/image-slider/image-slider.component';

@Component({
  selector: 'app-more',
  standalone: true,
  imports: [    CommonModule,
    RouterOutlet,
    FormsModule,
    ReactiveFormsModule,
    ImageSliderComponent,],
  templateUrl: './more.component.html',
  styleUrl: './more.component.scss'
})
export class MoreComponent {

  slides: any[] = [
    {
      url: 'https://html.com/wp-content/uploads/flamingo.webp',
      title: 'First Slide',
      description: 'test1',
    },
    {
      url: 'https://images.unsplash.com/photo-1542831371-29b0f74f9713?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aHRtbHxlbnwwfHwwfHx8MA%3D%3D',
      title: 'Second Slide',
      description: 'test2',
    }
  ];

}

The page doesnt load:
enter image description here
If i remove the OnInit function aswell as the OnInit interface, the page is loading and i can switch through the images by the buttons i implemented, but the autoplay isn't working since I am not using the OnInit Function


I've been trying to add "toastr" to my Angular17 project but injecting it into my components does not work. I added it using AngularCLI.
I'm getting the next error:
ERROR Error [NullInjectorError]: R3InjectorError(Standalone[_PDSLoginComponent])[InjectionToken ToastConfig -> InjectionToken ToastConfig -> InjectionToken ToastCo
nfig -> InjectionToken ToastConfig]:
NullInjectorError: No provider for InjectionToken ToastConfig!
Here's what my code contains:
import { Component, Output, EventEmitter, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { ToastrService, ToastNoAnimation } from 'ngx-toastr';

@Component({
  selector: 'app-pdslogin',
  standalone: true,
  imports: [
    FormsModule
  ],
  providers: [
    { provide: ToastrService, useClass: ToastrService },
    { provide: ToastNoAnimation, useClass: ToastNoAnimation }
  ],
  templateUrl: './pdslogin.component.html',
  styleUrls: ['./pdslogin.component.css']
})
export class PDSLoginComponent {
  loginData = {
    UserId: ''
  };
  @Output() loginEvent = new EventEmitter();
  onLogin() {
    this.loginEvent.emit(this.loginData);
    this.toastr.info("SHOWING TOASTR!!!","Info");
  }
  constructor(private router: Router, private toastr: ToastrService) { }
}

I have tried searching for a solution in forums and questions here in Stack Overflow but all of them are for previous versions of Angular, now Angular17 uses the property "standalone", so then it requires to import and inject right to the component.

Something I tried is adding it as provider in my 'main.ts' file but as well, didn't work.


I have an Angular 17 application that uses server-side rendering. The state of the application is managed using ngrx.
When I access the page, I can see that the page comes pre-rendered (by viewing the source of the page, for example), but once the page loads, Angular seems to start from scratch.
For example, I have some labels that are obtained through an HTTP request. Initially I see the labels in the page, but then Angular starts and clears the state, rendering  the labels blank. It then performs the HTTP request to fetch those labels and displays them again. The end-result is correct but there is a flicker when Angular takes over. From what I read it should be reusing the state from the server.
On the browser console, I can see the following:
Angular hydrated 12 component(s) and 98 node(s), 0 component(s) were skipped. Learn more at https://angular.io/guide/hydration.

This seems to indicate the Angular was able to hydrate all my components. I have the Redux dev tools, and by checking them it seems that it is the store that is not being hydrated, as the initial state corresponds to the default state of the store while I would expect it to start from the state that came from the server.
What do I need to do to preserve the state of the store?


I've tried to implement a reactive form with formArray in angular17. I encountered this issue when you removed one item from the formArray from the top or from the middle.
here's the stackbiz for the issue reproduction.
reproduction path:

put some values in the film fields.
click the add film button to add another film to the form.
put some other values in the newly added film fields.
click on the remove film button under the first film fields.
observe the values in the film fields, the removed film field values are still showing on the dom. but in the below json where I display the form values are updated correctly.

I try to use ApplicationRef.tick(), ChangeDetectorRef.detectChanges(), and updateValueAndValidity() as other similar issues suggested, but no luck. try to use trackBy, but it doesn't do the trick also. Can someone tell me what I'm doing wrong here?
import { CommonModule } from '@angular/common';
import { ApplicationRef, ChangeDetectorRef, Component } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
  ReactiveFormsModule,
} from '@angular/forms';

@Component({
  selector: 'app-add-vehicle',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule],
  templateUrl: './add-vehicle.component.html',
  styleUrl: './add-vehicle.component.scss',
})
export class AddVehicleComponent {
  constructor(
    private fb: FormBuilder,
    private appRef: ApplicationRef,
    private cdr: ChangeDetectorRef
  ) {}

  addVehicleForm = this.fb.group({
    make: [''],
    model: [''],
    year: [''],
    films: this.fb.array([this.createFilmFormGroup()]),
  });

  createFilmFormGroup(): FormGroup {
    return this.fb.group({
      title: [''],
      releaseDate: [''],
      url: [''],
    });
  }

  get films(): FormArray {
    return this.addVehicleForm.get('films') as FormArray;
  }

  addFilm() {
    this.films.push(this.createFilmFormGroup());
  }

  removeFilm(index: number) {
    this.films.removeAt(index);

    this.addVehicleForm.reset(this.addVehicleForm.value);

    // not working
    // this.addVehicleForm.updateValueAndValidity();

    // not working
    // this.appRef.tick();

    //not woorking
    // this.cdr.detectChanges();
  }
}

Add Vehicle

  <form [formGroup]="addVehicleForm">

      Vehicle Make
      <input
        type="text"
        class="form-control"
        id="make"
        formControlName="make"
      />

      Vehicle Model
      <input
        type="text"
        class="form-control"
        id="model"
        formControlName="model"
      />

      Manufacture year
      <input
        type="text"
        class="form-control"
        id="ManufactureYear"
        formControlName="year"
      />

        @for (film of films.controls; track $index) {

          <input type="hidden" name="id" formControlName="id" />

            Title
            <input
              type="text"
              class="form-control"
              [id]="'title' + $index"
              formControlName="title"
            />

            Release Date
            <input
              type="text"
              class="form-control"
              [id]="'releaseDate' + $index"
              formControlName="releaseDate"
            />

            URL
            <input
              type="text"
              class="form-control"
              [id]="'url' + $index"
              formControlName="url"
            />

          <button type="button" (click)="removeFilm($index)">
            Remove Film
          </button>

        }

      <button type="button" (click)="addFilm()">Add Film</button>

  </form>

  {{ addVehicleForm.value | json }}


Icons don't work in Angular.
In the component.ts file:
import { MatIconModule } from '@angular/material/icon';

@Component({
  selector: 'app-dashboard-space',
  standalone: true,
  imports: [
    MatIconModule,
  ],

And in the HTML file:
<div class="w-[20rem] h-[20rem] bg-yellow-100">
  <mat-icon>grade</mat-icon>
</div>

and what I see is the text: "gra"
Of course, I ran npm install --save @angular/material.
But the console is empty.
Do you have any idea?


I'm trying to add a table in my Angular app from Angular Material@17.2.1 (as shown here).
I copy / pasted the code from the Angular Material official documentation but I still get the error:

Can't bind to 'dataSource' since it isn't a known property of 'table'

I tried the following:
Replacing table tag with mat-table, resulting in

mat-table is not a known element

Deleting the brackets in [dataSource]="dataSource" as dataSource="dataSource", resulting in (Webdeveloper console error this time, this could be the solution but I don't know how to fix it even after some searches)

Can't bind to 'matHeaderRowDef' since it isn't a known property of 'tr' (used in the '_UsersComponent' component template).

importing MatTableModule from '@angular/material' instead of '@angular/material/table' in app.module.ts, resulting in

@angular/material has no expôrted member MatTableModule

Add import {CdkTableModule} from '@angular/cdk/table'; and importing it, changing nothing.
The MatTableModule is declared and imported in app.module.ts, where the UsersComponent using it is also declared and imported.
Here are all versions used in the project:
@angular-devkit/architect       0.1702.2
@angular-devkit/build-angular   17.2.2
@angular-devkit/core            17.2.2
@angular-devkit/schematics      17.2.2
@angular/cdk                    17.2.1
@angular/cli                    17.2.2
@angular/material               17.2.1
@schematics/angular             17.2.2
rxjs                            7.8.1
typescript                      5.3.3
zone.js                         0.14.4
Here is my app.module.ts file's content:
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { BrowserModule } from '@angular/platform-browser';

import { MatListModule } from '@angular/material/list';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatSidenavModule } from '@angular/material/sidenav';

import { AppComponent } from './app.component';
import { TopbarComponent } from './topbar/topbar.component';
import { LeftmenuComponent } from './leftmenu/leftmenu.component';
import { NavleftbarComponent } from './navleftbar/navleftbar.component';

import { MatIconModule } from '@angular/material/icon';
import {MatTableModule} from '@angular/material/table';
import { MatButtonModule } from '@angular/material/button';
import {CdkTableModule} from '@angular/cdk/table';

import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { UsersComponent } from './users/users.component';

@NgModule({
  declarations: [
    AppComponent,
    TopbarComponent,
    LeftmenuComponent,
    NavleftbarComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    MatToolbarModule,
    MatSidenavModule,
    MatListModule,
    MatButtonModule,
    MatIconModule,
    MatTableModule,
    UsersComponent,
    CdkTableModule
  ],
  providers: [
    provideAnimationsAsync()
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Here's the users.component.ts's file content:
import { Component } from '@angular/core';
import { MatTableModule } from '@angular/material/table';

export interface UserElement {
  firstname: string;
  lastName: string;
  email: string;
  microsoftEmail: string;
  class: string;
}

const ELEMENT_DATA: UserElement[] = [{
  firstname: "Pierrick",
  lastName: "MARTELLIERE",
  email: "p.martelliere@gmail.com",
  microsoftEmail: "pierrick@coxidev.com",
  class: "GPME24"
}];

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrl: './users.component.css',
  standalone: true,
})

export class UsersComponent {
  displayedColumns: string[] = ['firstName', 'lastName', 'email', 'microsoftEmail', 'class'];
  dataSource = ELEMENT_DATA;
  clickedRows = new Set<UserElement>();
}

And the users.component.html:

  <ng-container matColumnDef="firstName">
     Prénom
     {{element.position}}
  </ng-container>

  <ng-container matColumnDef="lastName">
     Name
     {{element.name}}
  </ng-container>

  <ng-container matColumnDef="email">
     Email
     {{element.weight}}
  </ng-container>

  <ng-container matColumnDef="microsoftEmail">
     Compte Microsoft
     {{element.symbol}}
  </ng-container>

  <ng-container matColumnDef="class">
     Classe
     {{element.symbol}}
  </ng-container>

I really don't see what I am missing, some help would be welcome.


My application runs fine. My application is a standalone component app. When I try to test the component, I get the error mentioned in the title in Karma.
Imports of my component
import { Component } from '@angular/core';
import {MatSelectModule} from '@angular/material/select';
import {MatFormFieldModule} from '@angular/material/form-field';
import { NavigationComponent } from '../../../0_navigation/navigation.component';
import jsonDataShipments from '../../../../../assets/shipments.json';

@Component({
  selector: 'app-sort-functionality',
  standalone: true,
  imports: [NavigationComponent, MatFormFieldModule, MatSelectModule],
  templateUrl: './sort-functionality.component.html',
  styleUrl: './sort-functionality.component.css'
})

Config of my app
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(), provideAnimationsAsync(),
  ],
};

Error
Error: NG05105: Unexpected synthetic property @transitionMessages found. Please make sure that:
  - Either `BrowserAnimationsModule` or `NoopAnimationsModule` are imported in your application.
  - There is corresponding configuration for the animation named `@transitionMessages` defined in the `animations` field of the `@Component` decorator (see https://angular.io/api/core/Component#animations).

If I import BrowserAnimationsModule
I get this error
Uncaught (in promise): Error: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.
Error: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.


upgrading from angular 14 to 17 I encountered issue with ng test. It is not working anymore.
Error:
PS C:\ForAngular17\src\ng\cat-ng> ng test
One or more browsers which are configured in the project's Browserslist configuration will be ignored as ES5 output is not supported by the Angular CLI.
Ignored browsers: ie 11, ie 10, ie 9, kaios 2.5, op_mini all
✔ Browser application bundle generation complete.
##teamcity[blockOpened name='JavaScript Unit Tests' flowId='']

Error: error TS2688: Cannot find type definition file for '@angular/localize'.
  The file is in the program because:
    Entry point of type library '@angular/localize' specified in compilerOptions

    12 03 2024 09:26:26.230:INFO [karma-server]: Karma v6.4.3 server started at http://localhost:9876/
    12 03 2024 09:26:26.232:INFO [launcher]: Launching browsers ChromeHeadlessNoSandbox with concurrency unlimited
    12 03 2024 09:26:26.233:ERROR [karma-server]: Error: Found 1 load error
        at Server.<anonymous> (C:\ForAngular17\src\ng\cat-ng\node_modules\karma\lib\server.js:243:26)
        at Object.onceWrapper (node:events:631:28)
        at Server.emit (node:events:529:35)
        at emitListeningNT (node:net:1851:10)
        at process.processTicksAndRejections (node:internal/process/task_queues:81:21)

tsconfig.spec.json code:
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/spec",
    "types": [
      "jasmine",
      "node",
      "@angular/localize"
    ]
  },
  "files": [
    "test.ts",
    "polyfills.ts"
  ],
  "include": [
    "**/*.spec.ts",
    "**/*.d.ts"
  ]
}

package.json code
    {
  "name": "cat-ng",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "build-prod": "ng build --configuration production",
    "build-azure": "ng build --azure",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@ag-grid-community/angular": "^28.0.0",
    "@ag-grid-community/client-side-row-model": "^28.0.2",
    "@ag-grid-community/core": "^28.0.2",
    "@ag-grid-enterprise/clipboard": "^28.0.2",
    "@ag-grid-enterprise/column-tool-panel": "^28.0.2",
    "@ag-grid-enterprise/excel-export": "^28.0.2",
    "@ag-grid-enterprise/menu": "^28.0.2",
    "@ag-grid-enterprise/range-selection": "^28.0.2",
    "@ag-grid-enterprise/server-side-row-model": "^28.0.2",
    "@ag-grid-enterprise/set-filter": "^28.0.2",
    "@angular/animations": "^17.2.4",
    "@angular/cdk": "^17.2.2",
    "@angular/common": "^17.2.4",
    "@angular/compiler": "^17.2.4",
    "@angular/core": "^17.2.4",
    "@angular/forms": "^17.2.4",
    "@angular/localize": "^17.2.4",
    "@angular/material": "^17.2.2",
    "@angular/material-moment-adapter": "^17.2.2",
    "@angular/platform-browser": "^17.2.4",
    "@angular/platform-browser-dynamic": "^17.2.4",
    "@angular/platform-server": "^17.2.4",
    "@angular/router": "^17.2.4",
    "@azure/msal-angular": "^3.0.13",
    "@azure/msal-browser": "^3.10.0",
    "@fortawesome/angular-fontawesome": "^0.7.0",
    "@fortawesome/fontawesome-free": "^5.12.1",
    "@fortawesome/fontawesome-svg-core": "^1.2.21",
    "@microsoft/applicationinsights-web": "^2.8.4",
    "@ng-bootstrap/ng-bootstrap": "^13.0.0",
    "@ngrx/data": "^17.1.1",
    "@ngrx/effects": "^17.1.1",
    "@ngrx/entity": "^17.1.1",
    "@ngrx/router-store": "^17.1.1",
    "@ngrx/schematics": "^17.1.1",
    "@ngrx/store": "^17.1.1",
    "@ngrx/store-devtools": "^17.1.1",
    "@ngtools/webpack": "^17.2.3",
    "@popperjs/core": "^2.11.5",
    "angular2-text-mask": "^9.0.0",
    "bignumber.js": "^9.1.1",
    "bootstrap": "^5.3.3",
    "bootstrap-scss": "^5.3.3",
    "core-js": "^2.6.9",
    "date-input-polyfill": "^2.14.0",
    "file-saver": "^2.0.5",
    "flag-icon-css": "^3.2.0",
    "font-awesome": "^4.7.0",
    "fortawesome": "^0.0.1-security",
    "jquery": "^3.7.1",
    "karma-firefox-launcher": "^2.1.3",
    "mathjs": "^10.6.4",
    "moment": "^2.29.3",
    "ng-bootstrap": "^1.6.3",
    "ng-click-outside2": "^14.0.1",
    "ng-sidebar": "^8.1.1",
    "ngx-angular-query-builder": "^17.0.0",
    "ngx-toastr": "^18.0.0",
    "popper.js": "^1.16.1",
    "rxjs": "^7.8.1",
    "rxjs-compat": "^6.5.3",
    "subsink": "^1.0.1",
    "tether": "^1.4.7",
    "url-search-params-polyfill": "^5.0.0",
    "zone.js": "~0.14.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^17.2.3",
    "@angular/cli": "^17.2.3",
    "@angular/compiler-cli": "^17.2.4",
    "@angular/language-service": "^17.2.4",
    "@types/jasmine": "~3.6.0",
    "@types/jasminewd2": "~2.0.4",
    "@types/jquery": "^3.5.14",
    "@types/node": "^10.14.14",
    "codelyzer": "^6.0.0",
    "jasmine-core": "^5.1.2",
    "jasmine-spec-reporter": "~7.0.0",
    "karma": "^6.4.3",
    "karma-chrome-launcher": "^3.2.0",
    "karma-coverage-istanbul-reporter": "^3.0.3",
    "karma-jasmine": "^5.1.0",
    "karma-jasmine-html-reporter": "^2.0.0",
    "karma-junit-reporter": "^2.0.1",
    "karma-teamcity-reporter": "^1.1.0",
    "protractor": "^7.0.0",
    "puppeteer": "^1.19.0",
    "ts-node": "^7.0.1",
    "tslint": "^6.1.3",
    "typescript": "5.3.3",
    "webpack-bundle-analyzer": "^3.4.1"
  }
}

What is the possible here? Thank you!


I have a component (see: it is a standalone one):
@Component({
  standalone: true, // <--- See here
  selector: "app-login",
  imports: [FormsModule, CommonModule],
  templateUrl: "./login.component.html",
  styleUrl: "./login.component.css"
})
export class LoginComponent {
  constructor(private authService: AuthService) {}
}

And the service is (see, it requires HttpClient to be injected):
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export default class AuthService {
  constructor(private http: HttpClient) {} // <--- See here: if I remove this httpClient, it works.
}

It does not works:
ERROR NullInjectorError: R3InjectorError(Standalone[e])[e -> e -> e -> e]:
  NullInjectorError: No provider for e!

If I remove the httpClient from the constructor of the service, it works (but it does nothing). It seem to me that the injection of the HttpClient inside the service is not working.
Any clue?
Version: Angular 17
PS: lot's of details removed :-)


Clicking on the second button in a @for-list changes the state to true of the 2nd and 3rd buttons when using it as a component. When using the button from the component directly, it works correctly: the state of the 2nd button is true, while the state of the 3rd button is still false. Why is that?
Stackblitz
app.component.ts:
@Component({
  selector: 'app-root',
  standalone: true,
  template: `
    Clicking on second button changes state of 2nd and 3rd button when using as component

    When using the button component directly, it works correctly

    undone:
    @for (todo of undoneTodos; track $index) {

      <app-slider [id]="'undone-'+$index" [active]="todo.done" (activeChange)="toggle(todo)"></app-slider>
    }

    done:
    @for (todo of doneTodos; track $index) {
      <app-slider [id]="'done-'+$index" [active]="todo.done" (activeChange)="toggle(todo)"></app-slider>
    }
  `,
  imports: [SliderComponent]
})
export class App {
  undoneTodos: Todo[] = [];
  doneTodos: Todo[] = [];

  private todos: Todo[] = [
    {id: 1, done: false },
    {id: 2, done: false },
    {id: 3, done: false },
  ]

  constructor() {
    this.buildTodos();
  }

  toggle(todo: Todo) {
    todo.done = !todo.done

    this.buildTodos();
  }

  private buildTodos() {
    this.doneTodos = this.todos.filter(x => x.done);
    this.undoneTodos = this.todos.filter(x => !x.done);
  }
}

export interface Todo {
  id?: number;
  done: boolean;
}

slider.component.ts:
import { Component, EventEmitter, Input, Output } from "@angular/core";

@Component({
  selector: 'app-slider',
  standalone: true,
  template: '<button (click)="onClick($event)">{{ active }}</button>',
})
export class SliderComponent {
  @Input() active: boolean = false;
  @Output() activeChange: EventEmitter<boolean> = new EventEmitter<boolean>();

  onClick(event: Event) {
    event.stopImmediatePropagation();

    this.active = !this.active;
    this.activeChange.emit(this.active);
  }
}


I have a timer for 10 minutes and I need to show it in my angular app that has many routing links (pages). I know that angular is one page site but you can browse to different areas by using routing. Since this is true, how to show the timer in the main app component for all the routing links without resetting the timer everytime i go to difffent routing link?
timer code:
typescript file:
timer(minute) {
    // let minute = 1;
    let seconds: number = minute * 60;
    let textSec: any = "0";
    let statSec: number = 60;

const prefix = minute < 10 ? "0" : "";

const timer = setInterval(() => {
  seconds--;
  if (statSec != 0) statSec--;
  else statSec = 59;

  if (statSec < 10) {
    textSec = "0" + statSec;
  } else textSec = statSec;

  this.display = `${prefix}${Math.floor(seconds / 60)}:${textSec}`;

  if (seconds == 0) {
    console.log("finished");
    clearInterval(timer);
  }
}, 1000);

}

html file:
{{display}}

if I put this in main app component and tried to go to different routing link it will reset the timer again and I don't want this to happened. Let us say main page is properties and second one is contacts, if i switch between then the timer resets again and again, I don't want that.


I am trying to add a bootstrap toaster to my angular project. I am using angular 17 with standalone components.
I am trying to follow what was done in this github repository but my project is standalone.
Running ng serve is successful but when I am trying to access http://localhost:4200/ I get the following error
[vite] Internal server error: document is not defined
      at enableDismissTrigger (D:\dev\git-2.0\base-templates\angular\angular-bootstrap-5-base\node_modules\bootstrap\dist\js\bootstrap.esm.js:802:19)
      at eval (D:\dev\git-2.0\base-templates\angular\angular-bootstrap-5-base\node_modules\bootstrap\dist\js\bootstrap.esm.js:884:1)
      at async instantiateModule (file:///D:/dev/git-2.0/base-templates/angular/angular-bootstrap-5-base/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54758:9) (x6)

https://stackblitz.com/~/github.com/Chrispie/code-problems on my issue-creating-bootstrap-5-toaster-with-angular-17-standalone branch:

I added my sample project where I have reproduced the error to my github repo.
Any idea as to what am I doing wrong here or what does it mean in this context?
For completeness sake I am outlining below what I have done.
I created a new angular project with scss and added the following 2 dependencies
npm i bootstrap
npm i @types/bootstrap --save-dev

A toast and a toaster component is added with a service and 2 models. The main app component has a few buttons to launch the toasts.
When running I am expecting it to look something like this


I am trying to connect to an API through a service that I have created with Angular but when I enter the page, console browser returns the following error:
main.ts:5 ERROR NullInjectorError: R3InjectorError(Standalone[_HomeComponent])[_EventosService -> _EventosService -> _EventosService -> _HttpClient -> _HttpClient]:
  NullInjectorError: No provider for _HttpClient!
    at NullInjector.get (core.mjs:1654:27)
    at R3Injector.get (core.mjs:3093:33)
    at R3Injector.get (core.mjs:3093:33)
    at injectInjectorOnly (core.mjs:1100:40)
    at Module.ɵɵinject (core.mjs:1106:42)
    at Object.EventosService_Factory [as factory] (eventos.service.ts:8:28)
    at core.mjs:3219:47
    at runInInjectorProfilerContext (core.mjs:866:9)
    at R3Injector.hydrate (core.mjs:3218:21)
    at R3Injector.get (core.mjs:3082:33)

I am using Angular version 17 in my project and doing the imports in the same HomeComponent component. The affected files are the following.
home.component.ts
import { Component, OnInit } from '@angular/core';
import { EventosService } from '../../shared/services/eventos/eventos.service';
import { Observable } from 'rxjs';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';

@Component({
  selector: 'app-home',
  standalone: true,
  templateUrl: './home.component.html',
  imports: [CommonModule, HttpClientModule],
  styleUrls: ['./home.component.sass']
})

export class HomeComponent implements OnInit{

  constructor( private es: EventosService ) {}

  usuarios : any = {};

  ngOnInit(): void {
    this.es.getEventos().subscribe(data => {
      this.usuarios = data;
    });
    console.log(this.usuarios);
  }

}

eventos.services.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable(
  {providedIn: 'root'}
)
export class EventosService {

  private baseUrl = "https://localhost:7019/api";

  constructor( private http: HttpClient ) { }

  public getEventos(): Observable<any> {
    return this.http.get(`${this.baseUrl}/Usuarios`);
  }

}

WARNING: I am aware that the service is called "Eventos" and I am calling "Usuarios" in the API, it is to test that it returns me some result even if it is by console.
INFO
I am using Angular 17 with the default settings although the project is migrated from Angular 16. The API is made with .NET but with other tools I can connect well to it and launch requests that return results.


I am using the command ng new <project-name> to create a new angular project. When the project is created, though it runs properly, there is no angular module present in the project.
The ng new command is generating a project only with StandAlone components.
I am using angular 17


I have a canDeactivateGuard which returns from component's MatDialog for unsaved action.
My problem is I am unable to test the functional guard and getting error -
TypeError: Cannot read properties of undefined (reading 'canUserExitAlertDialog')
Here is the Guard-
import { CanDeactivateFn } from '@angular/router';
import { Observable, map } from 'rxjs';

export const canDeactivateGuard: CanDeactivateFn<any> = (
  component,
  route,
  state
): Observable<boolean> | boolean => {
  return component.canUserExitAlertDialog('back').pipe(
    map((result) => {
      console.log(result);
      return result === 'discard';
    })
  );
};

Here is my component's method which the guard is calling-
Note: I have a mat-dialog which have two buttons - 'discard' and 'cancel'. On 'discard' click user is redirected to home page.
canUserExitAlertDialog(key: string): Observable<any> {
//I have a condition in the alert component based on this key
    if (this.hasFormSaved) { //if any changes are saved then not considered
      return of('discard');
    }
    const dialogConfig = new MatDialogConfig();
    dialogConfig.disableClose = true;
    dialogConfig.autoFocus = true;
    dialogConfig.data = { action: key, redirect: 'home' };
    if (this.wasFormChanged || this.form.dirty) {
      const dialogRef = this.dialog.open(AlertComponent, dialogConfig);
      return dialogRef.afterClosed();
    } else {
      this.dialog.closeAll();
      return of('discard');
    }
  }

Code in Dialog Alert component:
export class AlertComponent {
  userAction!: any;
  alertMsg = 'Are you sure you want to discard the changes?';
  unsavedChanges = 'This will reload the page';
  constructor(
    @Inject(MAT_DIALOG_DATA) data: any,
    @Inject(Window) private window: Window,
    private dialogRef: MatDialogRef<AlertComponent>
  ) {
    this.userAction = data;
  }

  public onCancel(): void {
    this.dialogRef.close('cancel');
  }

  public onDiscard(): void {
    this.dialogRef.close('discard');
    if (this.userAction.action === 'something') { //key I passed from the main component
      console.log('do something');
   }
  }
}

Finally here is my code in CanDeactivate spec file-
describe('canDeactivateGuard functional guard', () => {
  let nextState: RouterStateSnapshot;
  let component: MyComponent;
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {},
          },
        },
      ],
    });
  });

  it('should be created', fakeAsync(() => {
    const activatedRoute = TestBed.inject(ActivatedRoute);
    const nextState = {} as RouterStateSnapshot;
    const currState = {} as RouterStateSnapshot;
    const guardResponse = TestBed.runInInjectionContext(() => {
      canDeactivateGuard(
        component,
        activatedRoute.snapshot,
        currState,
        nextState
      ) as Observable<any>;
    });
    expect(guardResponse).toBeTruthy();
  }));

I have tried to create a stub component and define the canUserExitAlertDialog method but didn't help.
Is there another way to do this test successfully? AS per angular, class level deactivate guard is deprecated.
Error here-
error message
Test Coverage-
enter image description here


I have Angular 17 Project. I want to display some charts in it. So I have installed following modules in my project

npm i ag-charts-community
npm install ag-charts-angular

I am trying to use existing example from AG Charts as written below:-
TS File
import { Component, OnInit, OnDestroy} from '@angular/core';
import { AgChartsAngular } from "ag-charts-angular";
import { AgChartOptions } from "ag-charts-community";

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

import { getData } from "./data";

@Component({
    selector: 'view-survey',
    // templateUrl: './viewsurvey.component.html',
    template: '<ag-charts-angular style="height: 100%" [options]="options"></ag-charts-angular> ',
    standalone: true,
    imports: [
        CommonModule,
        AgChartsAngular,
    ],
    providers: [],
})

export class ViewSurveyComponent implements OnInit, OnDestroy {
    public options:AgChartOptions;

    constructor() {
        this.options = {
            title: {
              text: "Apple's Revenue by Product Category",
            },
            subtitle: {
              text: "In Billion U.S. Dollars",
            },
            data: this.getData(),
            series: [
              {
                type: "bar",
                direction: "horizontal",
                xKey: "quarter",
                yKey: "iphone",
                yName: "iPhone",
              },
              {
                type: "bar",
                direction: "horizontal",
                xKey: "quarter",
                yKey: "mac",
                yName: "Mac",
              },
              {
                type: "bar",
                direction: "horizontal",
                xKey: "quarter",
                yKey: "ipad",
                yName: "iPad",
              },
              {
                type: "bar",
                direction: "horizontal",
                xKey: "quarter",
                yKey: "wearables",
                yName: "Wearables",
              },
              {
                type: "bar",
                direction: "horizontal",
                xKey: "quarter",
                yKey: "services",
                yName: "Services",
              },
            ],
          };

    }

    ngOnInit() {

    }

    ngOnDestroy() {

    }

    getData()
    {
return [
      {
        quarter: "Q1'18",
        iphone: 140,
        mac: 16,
        ipad: 14,
        wearables: 12,
        services: 20,
      },
      {
        quarter: "Q2'18",
        iphone: 124,
        mac: 20,
        ipad: 14,
        wearables: 12,
        services: 30,
      },
      {
        quarter: "Q3'18",
        iphone: 112,
        mac: 20,
        ipad: 18,
        wearables: 14,
        services: 36,
      },
      {
        quarter: "Q4'18",
        iphone: 118,
        mac: 24,
        ipad: 14,
        wearables: 14,
        services: 36,
      },
    ];
    }
}

I am getting below error which I am not able to resolve
ERROR Error: AG Charts - unable to resolve global window
    at ChartOptions.specialOverridesDefaults (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-community/dist/package/main.esm.mjs:3534:13)
    at ChartOptions (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-community/dist/package/main.esm.mjs:3135:34)
    at Function.createOrUpdate (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-community/dist/package/main.esm.mjs:32475:26)
    at Function.create (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-community/dist/package/main.esm.mjs:32375:36)
    at eval (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-angular/fesm2020/ag-charts-angular.mjs:16:56)
    at _ZoneDelegate.invoke (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/zone.js/fesm2015/zone-node.js:368:26)
    at _Zone.run (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/zone.js/fesm2015/zone-node.js:130:43)

    at context (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/@angular/core/fesm2022/core.mjs:14320:28)
    at AgChartsAngular.runOutsideAngular (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-angular/fesm2020/ag-charts-angular.mjs:62:38)
    at AgChartsAngular.ngAfterViewInit (g:/onmytune/IP/InsightsGather.com/Angular17-InsightsGather/node_modules/ag-charts-angular/fesm2020/ag-charts-angular.mjs:16:23)

Can you please help what am I missing here?


I would like to initialize some important values when my application starts (Angular v17).
app.config.ts:
export const appConfig: ApplicationConfig = {
    providers: [
        ConfigService,
        ...
        {
            provide: APP_INITIALIZER,
            useFactory: (init: ConfigService) => init.load(),
            multi: true,
            deps: [ConfigService, HttpClient]
        }
    ]
};

config.service.ts:
@Injectable({
    providedIn: 'root',
})
export class ConfigService {
    private http = inject(HttpClient);

    private _config: any;
    private _user: AppUser;

    public getConfigUrl(key: string): string {
        return this._config.urls[key];
    }

    public load(): Promise<any> {
        return new Promise((resolve, reject) => {
            this._user = new AppUser(); <-- normally a request to my node-express server
            this._config = 'test';
            resolve(true);
        });
    }
}

Then I got this error when I ran the application and did not understand why.
ERROR TypeError: appInits is not a function
    at \_ApplicationInitStatus.runInitializers (core.mjs:31069:32)
    at core.mjs:34973:28
    at \_callAndReportToErrorHandler (core.mjs:31146:24)
    at core.mjs:34971:20
    at \_ZoneDelegate.invoke (zone.js:368:26)
    at Object.onInvoke (core.mjs:14424:33)
    at \_ZoneDelegate.invoke (zone.js:367:52)
    at \_Zone.run (zone.js:130:43)
    at \_NgZone.run (core.mjs:14275:28)
    at internalCreateApplication (core.mjs:34948:23)


NG05100: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.

import { Component, OnInit } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { Dropdown, DropdownItem, DropdownModule } from 'primeng/dropdown';  interface City {   name: string;   code: string; }   @Component({   selector: 'app-dropdown',   standalone: true,   imports: [FormsModule,DropdownModule,BrowserAnimationsModule],   templateUrl: './dropdown.component.html',   styleUrl: './dropdown.component.css',   providers: []    }) export class DropdownComponent implements OnInit{   cities: City[] | undefined;    selectedCity: City | undefined;   ngOnInit() {     debugger;     this.cities = [         { name: 'New York', code: 'NY' },         { name: 'Rome', code: 'RM' },         { name: 'London', code: 'LDN' },         { name: 'Istanbul', code: 'IST' },         { name: 'Paris', code: 'PRS' }     ];   }  }

core.mjs:6531 ERROR Error: NG05100: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.     at new _BrowserModule (platform-browser.mjs:1258:13)     at Object.BrowserModule_Factory [as useFactory] (platform-browser.mjs:1282:14)     at Object.factory (core.mjs:3322:38)     at core.mjs:3219:47     at runInInjectorProfilerContext (core.mjs:866:9)     at R3Injector.hydrate (core.mjs:3218:21)     at R3Injector.get (core.mjs:3082:33)     at injectInjectorOnly (core.mjs:1100:40)     at ɵɵinject (core.mjs:1106:42)     at useValue (core.mjs:2854:73)

ERROR RuntimeError: NG05100: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.
    at new _BrowserModule (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29844:13)
    at Object.BrowserModule_Factory [as useFactory] (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29868:10)
    at Object.factory (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3965:32)
    at eval (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3886:35)
    at runInInjectorProfilerContext (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2525:5)
    at R3Injector.hydrate (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3885:11)
    at R3Injector.get (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3778:23)
    at injectInjectorOnly (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2634:36)
    at ɵɵinject (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2640:59)
    at useValue (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3610:67) {
  code: 5100
}

No output file changes.

Application bundle generation complete. [0.878 seconds]

ERROR RuntimeError: NG05100: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.
    at new _BrowserModule (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29844:13)
    at Object.BrowserModule_Factory [as useFactory] (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29868:10)
    at Object.factory (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3965:32)
    at eval (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3886:35)
    at runInInjectorProfilerContext (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2525:5)
    at R3Injector.hydrate (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3885:11)
    at R3Injector.get (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3778:23)
    at injectInjectorOnly (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2634:36)
    at ɵɵinject (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2640:59)
    at useValue (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3610:67) {
  code: 5100
}
ERROR RuntimeError: NG05100: Providers from the `BrowserModule` have already been loaded. If you need access to common directives such as NgIf and NgFor, import the `CommonModule` instead.
    at new _BrowserModule (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29844:13)
    at Object.BrowserModule_Factory [as useFactory] (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:29868:10)
    at Object.factory (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3965:32)
    at eval (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3886:35)
    at runInInjectorProfilerContext (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2525:5)
    at R3Injector.hydrate (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3885:11)
    at R3Injector.get (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3778:23)
    at injectInjectorOnly (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2634:36)
    at ɵɵinject (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:2640:59)
    at useValue (eval at instantiateModule (file:///E:/Angular%20off/login-page/node_modules/vite/dist/node/chunks/dep-G-px366b.js:54755:28), <anonymous>:3610:67) {
  code: 5100
}

we want to show data in dropdown


I have a select that controls a list that just doesn't seem to be working. The error I get in the console is
core.mjs:6531 ERROR Error: NG05105: Unexpected synthetic listener @transformPanel.done found. Please make sure that:

Either BrowserAnimationsModule or NoopAnimationsModule are imported in your application.

Typescript:
import { Component } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule } from '@angular/material/icon';
import { DatePipe } from '@angular/common';
import { MatListModule } from '@angular/material/list';
import { MatSelectModule } from '@angular/material/select';
import { MatTooltipModule } from '@angular/material/tooltip';
import { provideAnimations } from '@angular/platform-browser/animations';
import { MatFormFieldModule } from '@angular/material/form-field';
import { FormsModule } from '@angular/forms';

export interface legend {
  name: string;
  image: string;
  tooltip: string;
}
export interface maplist {
  name: string;
  legends: Array<legend>
}

@Component({
  selector: 'app-legend',
  standalone: true,
  imports: [MatListModule, MatIconModule, MatDividerModule, DatePipe,
    MatSelectModule, MatTooltipModule, MatFormFieldModule, FormsModule,
  ],
  providers: [
    provideAnimations()
  ],
  templateUrl: './legend.component.html',
  styleUrl: './legend.component.css',
})
export class LegendComponent {
  selectedValue: Array<legend> = [];

  maplistdata: maplist[] = [
    {
      name: "Echocondria",
      legends: [
        {
          name: "House",
          image: "",
          tooltip: "Living quarters for the residents."
        },
        {
          name: "Shop",
          image: "",
          tooltip: "Places to buy and sell goods."
        },
      ]
    },
    {
      name: "Echocondria Sewers",
      legends: [
        {
          name: "House",
          image: "",
          tooltip: "Living quarters for the residents."
        },
        {
          name: "Shop",
          image: "",
          tooltip: "Places to buy and sell goods."
        },
      ]
    },
  ]
}

HTML:
  <mat-form-field>
  <mat-label>Select an option</mat-label>
  <mat-select
    color="primary"
    [(ngModel)]="selectedValue" name="legendselect"
  >
    <mat-option>None</mat-option>
    @for (legend of maplistdata; track legend) {
        <mat-option [value]="legend.legends">{{legend.name}}</mat-option>
    }
   </mat-select>
  </mat-form-field>

  @for (legenditem of selectedValue; track legenditem) {
  <mat-list-item>
  <mat-icon matListItemIcon>folder</mat-icon>

 {{ legenditem.name }}

{{legenditem.tooltip}}

</mat-list-item>
  }

I've tried importing the modules in question but still get the same error or an error that the module is already included.


In the previous *ngIf directives we were able to chain multiple async operations to not repeat the async pipe in the template but to reuse them later as one subscription, now I want to use the same behavior using the new @if syntax provided in Angular 17, is it possible?
Old way:
<ng-container *ngIf="{
   test: test$ | async,
   anotherOne: anotherOne$ | async,
   // and so on...
} as data">
  <span *ngIf="data.test.length">Show something</span>
</ng-container

I want to replace the code above to use only @if statement
@if({
   test: test$ | async,
   anotherOne: anotherOne$ | async,
   // it doesn't work that way
} as data) {
   <!-- show something -->
}


My folder structure
I don't understand why the rendering is on the server side but the components are placed on the client because after building I see the components are in the browser folder. am I making a mistake here?
I tried turning off javascript to check if the components are being rendered on the server side, the result is that after turning off js, the website is still displayed, which means the website is still rendered on the server side.


I am using Angular version 17 cli
<div class="row" [class.dark-category-box]="themeService.isDark()" *ngIf="trendingCategories">

I get this error:
 Can't bind to 'ngIf' since it isn't a known property of 'div' (used in the
'CategoriesStyleThreeComponent' component template).
If the 'ngIf' is an Angular control flow directive, please make sure that either the
'NgIf' directive or the 'CommonModule' is included in the '@Component.imports' of this component.

This is the app.module:
    import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { BrowserModule } from '@angular/platform-browser';
import { NgxScrollTopModule } from 'ngx-scrolltop';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { CommonModule } from '@angular/common';
import {CategoriesStyleThreeComponent} from './components/common/categories-style-three/categories-style-three.component'

 @NgModule({
 declarations: [],
 imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    NgxScrollTopModule,
    HttpClientModule,
    CommonModule
 ],
 providers: [],
 bootstrap: [],
     exports: [CategoriesStyleThreeComponent]
 })
   export class AppModule { }

and my component code:
 import { Component, OnInit } from '@angular/core';
 import { ThemeCustomizerService } from '../theme-customizer/theme-customizer.service';
 import { RouterLink } from '@angular/router';
 import { CategoryService } from '../../../services/category.service';
 import { Category } from '../../../models/category.model';

@Component({
selector: 'app-categories-style-three',
standalone: true,
imports: [RouterLink],
templateUrl: './categories-style-three.component.html',
styleUrls: ['./categories-style-three.component.scss']
})
export class CategoriesStyleThreeComponent implements OnInit {
trendingCategories: Category[];
numCategories: number = 5;

isToggled = false;

constructor(public themeService: ThemeCustomizerService,
    private categoryService: CategoryService) {
    this.themeService.isToggled$.subscribe(isToggled => {
        this.isToggled = isToggled;
    });
}

toggleTheme() {
    this.themeService.toggleTheme();
}

ngOnInit(): void {
    this.loadTrendingCategories();
}

loadTrendingCategories(): void {
    this.categoryService.getTrendingCategories()
        .subscribe(categories => {
            this.trendingCategories = categories;
            console.log(categories);
        });
  }

 }


I have a website that is a Video Gallery of my Youtube, and this videos are builded in iframe tag.
But I want use some loading in this for loop, because when I open my page the load is slow.
What I do?
My Code:
`@for (link of youtubeLinks; track $index) {
    <div class="video-container mx-1 mb-2">
      <iframe #youtubeVideos
              width="315"
              height="560"
              [src]="getVideoSrc(link)"
              frameborder="0"
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
               allowfullscreen>
       </iframe>
    </div>
 }`

I used a @defer directive, but doesn't worked.
I wanted each iframe to be loaded as the page scrolled, or to each one to be loaded at a time, not all of them as soon as they entered the page.


We have updated our project into Angular 17.
I got this ERROR TypeError: this.router.events.filter is not a function In console.
Here Is the app.components.ts file code
import { AfterViewInit, Component, OnInit, Inject, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser } from '@angular/common';
import { Router, ActivatedRoute, NavigationEnd, RouterModule } from '@angular/router';
import { environment } from "../environments/environment";
import { Title, Meta } from '@angular/platform-browser';
import { WINDOW } from '@ng-toolkit/universal';
import { Idle, DEFAULT_INTERRUPTSOURCES } from '@ng-idle/core';
import { CookieService } from 'ngx-cookie-service';
import { NgIdleKeepaliveModule } from '@ng-idle/keepalive';
import { HttpClientModule } from '@angular/common/http';
import { LoadingComponent } from './shared/components/loading/loading.component';
import { DataService } from './shared/service/data.service';
import { LoaderService } from './shared/service/loader.service';
import { SeoService } from './shared/service/seo.service';

declare const ga: any;
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  standalone: true,
  imports: [RouterModule, NgIdleKeepaliveModule, LoadingComponent, HttpClientModule],
  providers: [{ provide: WINDOW, useValue: {} }]
})

export class AppComponent implements OnInit, AfterViewInit {
  title = 'motor-happy';
  serverName: String;
  idleState = 'Not started.';
  timedOut = false;
  lastPing?: Date = null;
  title1 = 'angular-idle-timeout';
  expiredDate: Date;
  constructor(@Inject(WINDOW) private window: any,
    @Inject(PLATFORM_ID) private platformId: Object,
    public router: Router,
    public activatedRoute: ActivatedRoute,
    public titleService: Title,
    public meta: Meta,
    public cookieService: CookieService,
    public dataService: DataService,
    public loaderSVC: LoaderService,
    public seoService: SeoService,
    public idle: Idle,
  ) {

    idle.setIdle(600);
    idle.setTimeout(600);
    idle.setInterrupts(DEFAULT_INTERRUPTSOURCES);

    idle.onTimeout.subscribe(() => {
      this.timedOut = true;
      localStorage.removeItem('authorisationToken');
      this.router.navigate(['/']);
    });
    this.reset();
    this.serverName = environment.name;

    this.activatedRoute.queryParams.subscribe(params => {
      let utm_CampaignSource = params['utm_CampaignSource'];
      let getCookie = this.cookieService.get('utm_fetch');

      if (utm_CampaignSource && (!getCookie)) {
        const dateNow = new Date();
        dateNow.setMinutes(dateNow.getMinutes() + 30);
        this.cookieService.set('utm_fetch', "Yes", dateNow, '', '', true);
      }
    });

  }

  reset() {
    this.idle.watch();
    this.timedOut = false;
  }

  ngAfterViewInit(): void {
    this.router.events.subscribe(event => {
      if (event instanceof NavigationEnd && isPlatformBrowser(this.platformId)) {
        if (this.serverName == "production") {
          ga('set', 'page', event.urlAfterRedirects);
          ga('send', 'pageview');
        }
      }
    });
  }

  ngOnInit() {
    this.seoService.createLinkForCanonicalURL();
    this.router.events.subscribe((evt) => {
      this.loaderSVC.startLoading();
      if (!(evt instanceof NavigationEnd)) {
        return;
      }
      setTimeout(() => {
        this.loaderSVC.stopLoading();
      });
      if (isPlatformBrowser(this.platformId)) {
        window.scrollTo(0, 0);

        const userAgent = window.navigator.userAgent;
        sessionStorage.setItem('userAgent', userAgent);
        sessionStorage.setItem('ipAddress', '0.0.0.0');
      }
    });

    this.router.events
      .filter((event) => event instanceof NavigationEnd)
      .map(() => this.activatedRoute)
      .map((route) => {
        while (route.firstChild) route = route.firstChild;
        return route;
      })
      .filter((route) => route.outlet === 'primary')
      .mergeMap((route) => route.data)
      .subscribe((event) => {
        this.updateDescription(event['description'], event['keywords'], event['title']);
      });
  }

  updateDescription(desc: string, keywords: string, title: string) {
    if (title) {
      this.titleService.setTitle(title);
    }
    if (desc) {
      this.meta.updateTag({ name: 'description', content: desc })
    }
    /*if(keywords){
      this.meta.updateTag({ name: 'keywords', content: keywords })
    }*/
  }
}

We have tried to update
this.router.events.filter
with
this.router.events.pipe(filter(event => event instanceof NavigationEnd)
But don't know how to map after that


X [ERROR] Expected $config.color.primary to be a valid M3 palette.
angular 17
I can't find the expected valid M3 palette for @angular/material-experimental anywhere.
tryied this in styles.scss:
@use "@angular/material" as mat;
@use "@angular/material-experimental" as matx;

$primary-palette: (
    0: #000000,
    10: #191027,
    20: #2b1a41,
    25: #3d245c,
    30: #4f2f76,
    35: #9257c5,
    40: #654083,
    50: #79539b,
    60: #9d80b7,
    70: #c1aed3,
    80: #e5dbef,
    90: #e5ddee,
    95: #e9e3ef,
    98: #ebe7ef,
    99: #efecf1,
    100: #ffffff,
);

$m3-custom-theme: (
    color: (
        primary: $primary-palette
    ),
);

$light-theme: matx.define-theme($m3-custom);

html,
body {
    height: 100%;
    @include mat.button-theme($light-theme);
}


I am having different levels of closure using *ngFor directive and the new @for block.  I have a parent component that creates multiple child components using a for loop:
        <app-active-problem class="panel" *ngFor="let activeProblem of summary.activeProblems" [activeProblem] = "activeProblem" (update)="updateActiveProblem($event);"></app-active-problem>
        <!--
        @for (activeProblem of summary.activeProblems; track $index) {
            <app-active-problem class="panel" [activeProblem] = "activeProblem" (update)="updateActiveProblem($event);"></app-active-problem>
        }-->
      </ng-container>

In the child component I accept the [activeProblem] input as either a ProblemGroup | NarrativeProblem class.  In order to effectively distinguish between the two and render a view.  I create two instance variables
  problemGroup?: ProblemGroup;
  narrativeProblem?: NarrativeProblem;

  ngOnInit(): void {
    if (this.activeProblem instanceof ProblemGroup) {
      this.problemGroup = this.activeProblem as ProblemGroup;
    } else {
      this.narrativeProblem = this.activeProblem;
    }
  }

Within this same view I have a click event handler that toggles the value under the problem group (essentially mutating the object).
            <input
              clrCheckbox
              type="checkbox"
              [checked]="p.value"
              (change)="toggle($event, $index)"
            />

If I have rendered the child component using @for when assigning activeProblem to problemGroup it loses it's reference, effectively creating a copy of the object.  So any mutations I do in the child component is not reflected in the original object.
If I have rendered the child component using *ngFor directive, then it works as expected, any mutations I make to problemGroup effectively points to activeProblem.
I am hoping I can get some clarity on why this is happening?


I'm using Angular 17 with the following code:
database.component.html
@for(user of (users | userPipe:filters); track user.id) {

        {{ user.name }}
        {{ user.surname }}
        {{ user.age }}

}
@empty {

        Empty

}

filters is a string array with the keywords for filtering the matched database entries.
database.pipe.ts
@Pipe({
    name: 'userPipe',
    pure: false
})
export class databasePipe implements PipeTransform {
    transform(values: Users[], filters: string[]): Users[] {

        if (!filters || filters.length === 0 || values.length === 0) {
            return values;
        }

        return values.filter((value: User) => {
            filters.forEach(filter => {
                const userNameFound = value.name.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
                const userSurnameFound = value.surname.toLowerCase().indexOf(filter.toLowerCase()) !== -1;
                const ageFound = value.age.toLowerCase().indexOf(filter.toLowerCase()) !== -1;

                if (userNameFound || userSurnameFound || ageFound) {

                    console.log("value: ", value);
                    return value;
                }
                return "";
            });
        });
    }
}

It is working and I can see matching entries with value: <value> in the browser console just fine but my filtered table just returns "Empty" and no data is shown.
Does anyone know why this happens?


We are using Angular 17 along with Reactive forms in our project.
We have written a custom directive which formats the output to US phone number format 111-222-3333.
What we are seeing is that when someone tries to copy a number into the field - the field gets formatted, but the validator is still saying it is not valid.
HTML Code:
 <input matInput phoneFormatterDirective placeholder="Enter Phone" formControlName="phone"
                class="inputEntry">

Typescript Code:
phone: new FormControl(null, [Validators.pattern('^[0-9]{3}-[0-9]{3}-[0-9]{4}$')])

Custom Directive Code:
import {Directive, HostListener} from '@angular/core';

@Directive({
  selector: '[phoneFormatterDirective]'
})
export class PhoneFormatterDirective {

  @HostListener('input', ['$event'])
  onKeyDown(event: KeyboardEvent) {
    event.preventDefault();
    const input = event.target as HTMLInputElement;
    console.log(input.value);
    let trimmed = input.value
      .replaceAll('-','')
      .replaceAll('(','')
    .replaceAll(')','')
    .replaceAll(/\s+/g, '');
    if (trimmed.length > 12) {
      trimmed = trimmed.substr(0, 12);
    }
    let numbers = [];
    numbers.push(trimmed.substr(0,3));
    if(trimmed.substr(3,2)!=="")
      numbers.push(trimmed.substr(3,3));
    if(trimmed.substr(6,3)!="")
      numbers.push(trimmed.substr(6,4));

    input.value = numbers.join('-');
    console.log(numbers.join("-"));
  }
}

Let's say I am trying to paste (555) 123-1234 - the value gets formatted to 555-123-1234, but the input says it is still invalid.
It would be valid if I deleted one character and then wrote it manually - which is a kind of strange behavior.


<mat-button-toggle-group appearance="legacy"    [(ngModel)]="selectedClockType">
        <mat-button-toggle *ngFor="let item of items" [value]="item" color="primary">
           {{ item.label }}
        </mat-button-toggle>
    </mat-button-toggle-group>

     @for (item of items; track:item.id) {
          <ng-container *ngComponentOutlet="item .component"></ng-container>
        }

     <ng-template #actionItesm let-data="data">{{data}} </ng-template>

component-a.html
    <ng-content></ng-content>

component-b.html
<ng-content></ng-content>

Am Trying to pass ngTemplate by using  below code
 <ng-container *ngComponentOutlet="item .component;content: actionItesm ></ng-container>

and  using  inside all the components that am using inside Items


I am creating an Angular project and having the following error, which makes my page unable to load:
ERROR NullInjectorError: R3InjectorError(Standalone[_AppComponent])[ActivatedRoute -> ActivatedRoute -> ActivatedRoute]:
NullInjectorError: No provider for ActivatedRoute!
Since it is Angular v17, I do not have AppModule on it.
This is my following code:
app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [provideRouter(routes)]
};

app.component.ts
import { Component, LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { SharedModule } from './shared/shared.module';
import localePT from '@angular/common/locales/pt';

registerLocaleData(localePT);
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [SharedModule, RouterOutlet, RouterLink],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [{provide: LOCALE_ID, useValue: 'pt-br'}]
})
export class AppComponent {
  title = "app";
}

app.routes.ts
import { Routes } from '@angular/router';
import { HomeComponent } from './features/pages/home/home.component';

export const routes: Routes = [
    { path: 'home', component: HomeComponent },
    { path: '', redirectTo: 'home', pathMatch: 'full' }
];

Thank you in advance!
I tried adding RouterModule.forRoot(routes) in AppComponent, but no success.
I tried to import ActivatedRoute on AppComponent, but it throwed another error: ERROR Error: NG0204: Can't resolve all parameters for ActivatedRoute: (?, ?, ?, ?, ?, ?, ?, ?).
I also tried to import ActivateRoute in AppComponent as the following, but it returns: ERROR Error: NG04002: Cannot match any routes. URL Segment: 'home'
import { Component, LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import { ActivatedRoute, RouterLink, RouterOutlet } from '@angular/router';
import { SharedModule } from './shared/shared.module';
import localePT from '@angular/common/locales/pt';
import { routes } from './app.routes';

registerLocaleData(localePT);
@Component({
  selector: 'app-root',
  standalone: true,
  imports: [SharedModule, RouterOutlet, RouterLink],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [{provide: LOCALE_ID, useValue: 'pt-br'}, {provide: ActivatedRoute, useValue: routes}]
})
export class AppComponent {
  title = "app";
}

Since Angular v17 does not have AppModule and does not need it, I did not create it.
I am expecting my page to load properly, it is not allowing it to load.


I'm developing an Angular application and encountering an issue with localStorage in my AuthService. When attempting to use localStorage to store the user's email for authentication purposes, I'm getting an error: "localStorage is not defined".
Here's a simplified version of my AuthService:
//auth.service.ts

import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';

@Injectable({
    providedIn: 'root',
})
export class AuthService {
    public isAuth = new BehaviorSubject<boolean>(false);

    constructor(private router: Router) {
        this.autoSignIn();
    }

    autoSignIn() {
        if (localStorage.getItem('email')) {
            this.isAuth.next(true);
            this.router.navigate(['/dashboard']);
        }
    }

    signIn(email: string) {
        localStorage.setItem('email', email);
        this.isAuth.next(true);
        this.router.navigate(['/dashboard']);
    }

    signOut() {
        localStorage.removeItem('email');
        this.isAuth.next(false);
        this.router.navigate(['/auth']);
    }
}

I've imported the necessary modules, including Injectable from @angular/core, and I'm using localStorage within my service methods.


I am trying to convert my code directives from Angular 16 to Angular 17. However, I am unable to achieve the reference in Angular 17 so that for both else it will refer to the same ng-template.

0; else noTracks">

Favorites

Recent

{{movies[movies.length-1].title}}
                    -
                    {{movies[movies.length-1].rating}}

Total

{{ movies.length}}

<ng-template #noTracks>

Favorites

Recent

NA

Total

0

</ng-template>

In Angular 17 I am trying to achieve the above using @if and @else without using || cause for type never error I will get. Further, I want how we can achieve this.
Note: Don't combine @if statements.
@if (movies) {
  @if (movies.length>0) {

Favorites

Recent

{{movies[movies.length-1].title}}
            -
            {{movies[movies.length-1].rating}}

Total

{{ movies.length}}

  } @else {

Favorites

Recent

NA

Total

0

  }
}


I created centralized error handling service using BehaviorSubject in Angular v 17.It does not working in the expected way!
The problem areas are :
NotificationService -->  the centralized error handler.
NotificationComponent --> Reusable User Friendly Error and Progress message showing popup modal,i directly added it in my   Appcomponent.
Surrender Pet Component --> Where i try to use the Notification for showing option.
I thik those BhaviourSubjects not emitting the data the way i expected
NotificationService:
    import { Injectable } from '@angular/core';
    import { BehaviorSubject, Subject } from 'rxjs';

    @Injectable({
    providedIn: 'root'
    })
    export class NotificationService {
       successMessageSubject = new BehaviorSubject<string | null>(null);
       errorMessageSubject = new BehaviorSubject<string | null>(null);

       successMessageAction$ = this.successMessageSubject.asObservable();
       errorMessageAction$ = this.errorMessageSubject.asObservable();

       setSuccessMessage(message: string) {
       this.successMessageSubject.next(message);
     }

   setErrorMessage(message: string) {
   this.errorMessageSubject.next(message);
    console.log(this.errorMessageSubject.getValue());
   }

   clearSuccessMessage() {
    this.successMessageSubject.next(null);
    }

    clearErrorMessage() {
      this.errorMessageSubject.next(null);
    }

   clearAllMessages() {
    this.clearSuccessMessage();
    this.clearErrorMessage();
     }
    }

NotificationComponent :
import { Component, OnInit, inject } from '@angular/core';
import { NotificationService } from '../../../core/services/notifiaction/notification.service';
import { AsyncPipe, CommonModule, NgIf } from '@angular/common';
import { tap } from 'rxjs';

@Component({
  selector: 'app-notification',
  standalone: true,
  imports: [NgIf,AsyncPipe,CommonModule],
  templateUrl: './notification.component.html',
  styleUrl: './notification.component.scss',

})
export class NotificationComponent implements OnInit {

   private notificationService:NotificationService = inject(NotificationService);

   successMessage$ = this.notificationService.successMessageAction$.pipe(
     tap((message)=>{
      if(message){
      console.log('clicked')
      setTimeout(()=>{
        this.notificationService.clearAllMessages()
      },5000)
    }
     })
   )

   errorMessage$ = this.notificationService.errorMessageAction$.pipe(
    tap((message)=>{
      console.log(message);
      if(message){
     console.log('clicked')
     setTimeout(()=>{
       this.notificationService.clearAllMessages()
     },5000)
    }
    })
  )

   ngOnInit(): void {
    console.log("initialized")
  }
  }

Surrender Pet Component
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { RouterLink } from '@angular/router';
import { ButtonComponent } from '../../../shared/components/button/button.component';
import { NgClass, NgIf, } from '@angular/common';
import { Component, inject } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { PetsAdopteService } from '../../../core/services/pets-adopte/pets-adopte.service';
import { SurrenderPet } from '../../../core/models/surrenderPet.model';
import { NotificationService } from '../../../core/services/notifiaction/notification.service';

@Component({
  selector: 'app-surrender-pet',
  standalone: true,
  imports: [
    ReactiveFormsModule,
    NgClass,
    RouterLink,
    NgIf,
    ButtonComponent,
    HttpClientModule
  ],
  providers:[PetsAdopteService,NotificationService],
  templateUrl: './surrender-pet.component.html',
  styleUrl: './surrender-pet.component.scss'
})
export class SurrenderPetComponent {

  private petAdopteService=inject(PetsAdopteService);
  private notificationService=inject(NotificationService);

  submitted:boolean = false;

  registerPet= new FormGroup({
    name: new FormControl<string>('',[Validators.required]),
    phoneNo:new FormControl<string>('',[Validators.required]),
    petType:new FormControl<string> ('',[Validators.required]),
    location:new FormControl<string>('',[Validators.required]),
    otherDetails:new FormControl<string>('',[Validators.required])
  })

  onSubmit(){
      this.submitted = true;
      if(this.registerPet.valid){
       this.petAdopteService.sendPetSurrender_Request(this.registerPet.value as SurrenderPet).subscribe(
        {
          next:(data)=>{
         console.log(data);
        }

        }
       )
      }
  }
}

Notification Component html template:

           <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
               <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"/>
           </svg>
           Success icon

{{successMessage}}

       <button type="button" class="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#toast-success" aria-label="Close">
           Close
           <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
               <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
           </svg>
       </button>

           <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
               <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"/>
           </svg>
           Success icon

{{errorMessage}}

       <button type="button" class="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#toast-success" aria-label="Close">
           Close
           <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
               <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
           </svg>
       </button>

The PetsAdopteService where i called the setMessages functions!

    import { HttpClient } from '@angular/common/http';
    import { Injectable, inject } from '@angular/core';
    import { EMPTY, Observable, catchError, tap } from 'rxjs';
    import { SurrenderPet } from '../../models/surrenderPet.model';
    import { environment } from '../../../../environments/environment.development';
    import { petsSurrenderEndpoints } from '../../constants/APIEndPoints/petsAdopte.EndPoints';
    import { NotificationService } from '../notifiaction/notification.service';

    @Injectable({
      providedIn: 'root'
    })
    export class PetsAdopteService {

    constructor() { }

    private http:HttpClient=inject(HttpClient);
    private notificationService=inject(NotificationService);

    sendPetSurrender_Request(payload:SurrenderPet):Observable<SurrenderPet>{
     return this.http.post<SurrenderPet>                                                                              (environment.apiUrl+petsSurrenderEndpoints?.createSurrenderRequest,payload).pipe(
        tap((data)=>{
        this.notificationService.setSuccessMessage('Your request sent successfully')
      }),
      catchError((error)=>{
        console.log(error)
         this.notificationService.setErrorMessage("eROR");
         return EMPTY;
      })
     )
     }
    }

Is there any way to fix this problem with out choosing signal, because i want  to learn more about rxjs!


Application runs perfectly fine with npm start, when it is built using ng build, it gives the following errors:
▲ [WARNING] Module 'amazon-quicksight-embedding-sdk' used by './dashboard.component.ts' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'qrcode' used by 'node_modules/@aws-amplify/ui-angular/fesm2020/aws-amplify-ui-angular.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'ts-access-control' used by './permission.service.ts' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'style-dictionary/lib/utils/deepExtend.js' used by 'node_modules/@aws-amplify/ui/dist/esm/theme/createTheme.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'style-dictionary/lib/utils/flattenProperties.js' used by 'node_modules/@aws-amplify/ui/dist/esm/theme/createTheme.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'lodash/kebabCase.js' used by 'node_modules/@aws-amplify/ui/dist/esm/theme/utils.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'style-dictionary/lib/utils/references/usesReference.js' used by 'node_modules/@aws-amplify/ui/dist/esm/theme/utils.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'google-libphonenumber' used by './phone.service.ts' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module '@aws-crypto/sha256-js' used by 'node_modules/@aws-amplify/auth/dist/esm/providers/cognito/apis/signOut.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'lodash/pickBy.js' used by 'node_modules/@aws-amplify/ui/dist/esm/machines/authenticator/utils.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

▲ [WARNING] Module 'lodash/merge.js' used by 'node_modules/@aws-amplify/ui/dist/esm/validators/index.mjs' is not ESM

  CommonJS or AMD dependencies can cause optimization bailouts.
  For more information see: https://angular.io/guide/build#configuring-commonjs-dependencies

I am willing to provide more information required to fix this issue.


I use angular 17
this is my app.routes.ts
export const routes: Routes = [
  { path: '', pathMatch: 'full', component: HomeComponent },
  { path: 'editors', component: EditorsComponent },
  { path: 'partners', component: PartnersComponent },
  { path: 'investors', component: InvestorsComponent },
  { path: 'telecoms', component: TelecomsComponent },
  { path: 'institutional', component: InstitutionalComponent },
  { path: 'universities', component: UniversitiesComponent },
  { path: 'influencers', component: InfluencersComponent },
  { path: 'ambassador', component: AmbassadorComponent },
];

and my app.config.ts
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, '/assets/i18n/', '.json');
}

const scrollConfig: InMemoryScrollingOptions = {
  scrollPositionRestoration: 'top',
  anchorScrolling: 'enabled',
};

const inMemoryScrollingFeature: InMemoryScrollingFeature =
  withInMemoryScrolling(scrollConfig);

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, inMemoryScrollingFeature),
    provideLottieOptions({
      player: () => import('lottie-web'),
    }),
    provideAnimations(),
    provideHttpClient(),
    TranslateModule.forRoot({
      defaultLanguage: 'en',
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        //useFactory: (http: HttpClient) => new CustomTranslateLoader(http),
        deps: [HttpClient]
      }
    }).providers!, provideClientHydration(), provideClientHydration(), provideClientHydration() ],
};

when I try to go on the page http://localhost/editor i got lot 404 error for example  http://localhost:4200/editors/assets/animations/editor_anim1.json 404
Angular add the name of the page in the path of the ressource. This path should be  http://localhost:4200/assets/animations/editor_anim1.json 404
When I from home then go on page editors and come back on home, the url is http://localhost:4200/editors  and when i go to editor again, now the url is localhost:4200/editors/editors
What's wrong with my routing config ?


The problem basically is that when I'm logged into the dashboard, every time I reload the browser page it renders the login component for an instant
TokenService
export class TokenService {
  isAuthentications: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
  constructor(@Inject(PLATFORM_ID) private platformId: Object) {
    const token = this.getToken();
    if(token){
      this.updateToken(true)
    }
  }

  setToken(token: string){
    this.updateToken(true);
    localStorage.setItem('user', token)
  }
  updateToken(status: boolean){
    this.isAuthentications.next(status)
  }
  getToken(): string | null{
    if (typeof window !== 'undefined' && window.sessionStorage) {
      return localStorage.getItem('user');
    }

    return null
  }
}

AuthGuard
export const authGuard: CanActivateFn = (route, state) =\> {
const tokenService = inject(TokenService)
const router = inject(Router)
// tokenService.isAuthentications.subscribe({
//   next: (v) =\> {
//     if(!v){
//         router.navigate(['/login'])
//     }
//   }
// })
// return true;

return tokenService.isAuthentications.pipe(map( (user) =\> {
if(!user){
return router.createUrlTree(['/login']);
}else{
return true
}
}))
};

Routes
export const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { path: '', redirectTo: 'login', pathMatch: 'full'},
  {path: '' , component: LayoutComponent, children: [
    {path: 'dashboard', component: DashboardComponent, canActivate: [authGuard]  }
  ]}
];

gif that shows the problem
I've tried other other approaches on how to secure the route however, whenever my guard should redirect to 'login' it has this behavior


I'm encountering an error in my Angular application's template file (dashboard.component.html). The error message is "Object is possibly 'undefined'." Here's the relevant part of the template causing the issue:

Dashboard

       @for(post of posts; track post.title){
        @if(post.id%2==0){

{{post.id}}-{{post.title}}

        }
       }

// dashboard.component.ts

import { Component } from '@angular/core';
import { AuthService } from '../auth.service';

@Component({
    selector: 'app-dashboard',
    standalone: true,
    imports: [],
    templateUrl: './dashboard.component.html',
    styleUrl: './dashboard.component.scss',
})

export class DashboardComponent {
    email = localStorage.getItem('email');
    posts:any;
    constructor(private authService: AuthService) {
        this.GetAllPosts();
    }

    signOut() {
        this.authService.signOut();
    }

    GetAllPosts(){
        this.authService.getAllPosts().subscribe((res)=>{
            this.posts = res;
        })
    }
}

The error specifically points to line 10, where I'm trying to iterate over posts using an @for loop and check if post.id % 2 == 0. However, TypeScript is flagging this as a potential error because posts might be undefined or null.
How can I modify this template code to handle the possibility that posts might be undefined while avoiding this error?


In my case ,
I have following block of code,
In which, i can store the info value in the *ngIf expression block and use in the template, how to do the same with newly introduced @if syntax in angular 17 ?
I couldn't find any samples / docs that can do the same using @if syntax.
<div *ngIf="getMatchingImage() as info">
        <img class="empty-cart-img" [src]="info.imageUrl" width="70%" decoding="async" loading="lazy" alt="Empty List">
        <figcaption>
          <ng-content></ng-content>
        </figcaption>
      </div>


Could anyone advise after Angular update up to 18 I got:
An unhandled exception occurred: (0 , os_1.availableParallelism) is not a function
In angular-errors.log
[error] TypeError: (0 , os_1.availableParallelism) is not a function at Object.<anonymous> (C:\Users\Zendbook\Documents\DILAU\tracker-users-web\node_modules\piscina\dist\src\index.js:37:54) at Module._compile (node:internal/modules/cjs/loader:1218:14) at Module._extensions..js (node:internal/modules/cjs/loader:1272:10) at Module.load (node:internal/modules/cjs/loader:1081:32) at Module._load (node:internal/modules/cjs/loader:922:12) at Module.require (node:internal/modules/cjs/loader:1105:19) at require (node:internal/modules/cjs/helpers:103:18) at Object.<anonymous> (C:\Users\Zendbook\Documents\DILAU\tracker-users-web\node_modules\piscina\dist\src\main.js:5:33) at Module._compile (node:internal/modules/cjs/loader:1218:14) at Module._extensions..js (node:internal/modules/cjs/loader:1272:10)
How to fix ?
try to find answer in google.


I have configured klaro cookie package in my Angular project with all the required configurations, but I want to change the icon besides count of service:

I want "+" and "-" icons accordingly when service section is open/close. Is there any way to customize it as per need?
Old icon doesn't fade away:


After upgrading my Angular core libraries to version 18, I migrated to Angular Material 18 by running:
ng update @angular/material
The update went smoothly but when I tried to compile my app I got the following error:
X [ERROR] Undefined function.
   ╷
14 │ $myapp-theme-primary: mat.define-palette(mat.$indigo-palette, A400, A100, A700);
   │                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  src\styles.scss 14:23  root stylesheet [plugin angular-sass]

    angular:styles/global:styles:2:8:
      2 │ @import 'src/styles.scss';
        ╵         ~~~~~~~~~~~~~~~~~

My styles.scss worked perfectly with the previous version of Angular Material (v.17). It looks as follows:
@use '@angular/material' as mat;
@include mat.core();

$myapp-theme-primary: mat.define-palette(mat.$indigo-palette, A400, A100, A700);
$myapp-theme-accent: mat.define-palette(mat.$indigo-palette);
$myapp-theme-warn: mat.define-palette(mat.$red-palette);

$myapp-theme: mat.define-light-theme((
  color: (
    primary: $myapp-theme-primary,
    accent: $myapp-theme-accent,
    warn: $myapp-theme-warn,
  )
));

@include mat.all-component-themes($myapp-theme);

How do I have to adapt my code in styles.scss in order to make it work with Angular Material 18?


I want to use the new @for syntax together with @empty to either show the user a table or some text telling there is no data.
With ngFor I usually checked the length of the data array. If not empty:

Add the table header
ngFor the data
Add the table footer

With the newer syntax I hoped to be able to combine those 3 steps above into the @for itself like this:
@for(order of licenseOverview.orders; track order.id; let firstRow = $first; let lastRow = $last) {
   @if(firstRow) {
       <table ...
   }

       {{ order.reference }}
       {{ ... }}

   @if(lastRow) {
       ...

   }
}
@empty {
No data for you!
 }

I expected this to just compile and render the table, but it seems like Angular can't handle this. Is there a way to get this to work?
EDIT: The error I get looks like this:
            @if(firstRow) {

                            {{ 'Order' }}
                            {{ 'Expected On' }}
                            {{ 'Status' }}

            } ---> Unexpected closing block