Getting Laravel Spatie Permissions - ExpressionChangedAfterItHasBeenCheckedError

1 day ago 1
ARTICLE AD BOX

I'm using Laravel as REST API.

My frontend should show

All Permission All Roles All Roles with their specific Permissions

My Errors (F12)

(11) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}] installHook.js:1 ERROR RuntimeError: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'can_accessDashboard'. Expression location: _Dashboard component It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook? Find more at https://v21.angular.dev/errors/NG0100 at Dashboard_For_12_Template (component?c=src%2Fap…1770823049874:27:19) dashboard.ts:46 (4) [{…}, {…}, {…}, {…}] installHook.js:1 ERROR RuntimeError: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Developer'. Expression location: _Dashboard component It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook? Find more at https://v21.angular.dev/errors/NG0100 at Dashboard_For_8_Template (component?c=src%2Fap…1770823049874:15:19) dashboard.ts:56 {roles: Array(4)} installHook.js:1 ERROR RuntimeError: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'undefined'. Current value: 'Developer'. Expression location: _Dashboard component It seems like the view has been created after its parent and its children have been dirty checked. Has it been created in a change detection hook? Find more at https://v21.angular.dev/errors/NG0100 at Dashboard_For_8_Template (component?c=src%2Fap…1770823049874:15:19)

Stack:

Angular v21 Laravel v12 Sanctum Spatie for Permission and Role System

Placeholder data

Backend sends data correctly, for example: 0 : {id: 1, name: 'permission', guard_name: 'web', created_at: '2026-02-11T14:02:10.000000Z', updated_at: '2026-02-11T14:02:10.000000Z'}

My Files:

FRONTEND

permissionRoleDatabase

import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { environment } from '../../../../../environments/environment'; @Injectable({ providedIn: 'root', }) export class PermissionRoleDatabase { constructor( private http: HttpClient ) {} public getAllPermissions(): Observable<any> { const url = environment.apiURL + '/getAllPermissions'; return this.http.get(url); } public getAllRoles(): Observable<any> { const url = environment.apiURL + '/getAllRoles'; return this.http.get(url); } public getUserPermissions(): Observable<any> { const url = environment.apiURL + '/getUserPermissions'; return this.http.get(url); } public getAllRolesWithPermissions(): Observable<any> { const url = environment.apiURL + '/getAllRolesWithPermissions'; return this.http.get(url); } }

dashboard.ts

import { Component, inject, PLATFORM_ID } from '@angular/core'; import { MatTabsModule } from '@angular/material/tabs'; import { PermissionRoleDatabase } from '../../shared/services/permission/database/permission.database'; import { permissionModel } from './models/allPermissions.model'; import { roleModel } from './models/allRoles.model'; import { rolePermissionModel } from './models/rolePermissions.model'; import { isPlatformBrowser } from '@angular/common'; @Component({ selector: 'app-dashboard', imports: [MatTabsModule], templateUrl: './dashboard.html', styleUrl: './dashboard.scss', }) export class Dashboard { private permissionRoleDatabase = inject(PermissionRoleDatabase); private platformId = inject(PLATFORM_ID); protected allPermissions: permissionModel[] = []; protected allRoles: roleModel[] = []; protected rolePermissions: rolePermissionModel[] = []; ngOnInit() { if (!isPlatformBrowser(this.platformId)) return; this.getAllPerms(); } private getAllPerms(): void { this.permissionRoleDatabase.getAllPermissions().subscribe({ next: (res) => { this.allPermissions = res; console.log(res); }, error: (err) => { console.error('Error getting Permissions', err); }, }); this.permissionRoleDatabase.getAllRoles().subscribe({ next: (res) => { this.allRoles = res; console.log(res); }, error: (err) => { console.error('Error getting Roles', err); }, }); this.permissionRoleDatabase.getAllRolesWithPermissions().subscribe({ next: (res) => { this.rolePermissions = res; console.log(res); }, error: (err) => { console.error('Error getting Roles with Permissions', err); }, }); } }

dashboard.html

<mat-tab-group> <mat-tab label="Dashboard"> <div> <p>i dunno lol</p> </div> </mat-tab> <mat-tab label="User Management"> <div> @for (data of allRoles; track data.id ) { <li> {{ data.name }} </li> } </div> </mat-tab> <mat-tab label="Role Management"> <div> @for (data of allPermissions; track data.id ) { <li> {{ data.name }} </li> } </div> </mat-tab> </mat-tab-group>

What I've tried:

place my getAllPerms() into constructor. Place my getAllPerms() into ngAfterContentInit. Playe my getAllPerms() into a setTimeout. setTimeout(() => { this.getAllPerms(); }, 0); The data is shown correctly, but nevertheless the errors in my Console appear Using ngAfterContentInit() instead of ngOnInit()
Read Entire Article