New starter apps#169
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors and updates the Angular, React, and Vue starter templates to use the latest versions of Siemens iX (v5) and other core dependencies, while streamlining the project structures and migrating tests to Vitest. The code review feedback focuses on improving the Angular starter by leveraging the built-in routerLinkActive directive instead of a custom route-matching helper, which simplifies the main application component. Additionally, the feedback recommends removing unused imports in the configuration files and implementing safer null/undefined checks when handling form input events in both the Angular and Vue starters.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| <a routerLink="" tabindex="-1"> | ||
| <ix-menu-item [icon]="icons.iconHome" [attr.active]="isActiveRoute('/') ? '' : null"> | ||
| Get Started | ||
| </ix-menu-item> | ||
| </a> | ||
| <a routerLink="forms" tabindex="-1"> | ||
| <ix-menu-item [icon]="icons.iconTextDocument" [attr.active]="isActiveRoute('/forms') ? '' : null"> | ||
| Forms | ||
| </ix-menu-item> | ||
| </a> | ||
| <a routerLink="charts" tabindex="-1"> | ||
| <ix-menu-item [icon]="icons.iconPiechart" [attr.active]="isActiveRoute('/charts') ? '' : null"> | ||
| Charts | ||
| </ix-menu-item> | ||
| </a> | ||
| <a routerLink="grids" tabindex="-1"> | ||
| <ix-menu-item [icon]="icons.iconTable" [attr.active]="isActiveRoute('/grids') ? '' : null"> | ||
| Grids | ||
| </ix-menu-item> | ||
| </a> |
There was a problem hiding this comment.
Instead of using a custom isActiveRoute helper method with manual URL string matching, we can leverage Angular's built-in routerLinkActive directive. This is more robust, handles query parameters/hash locations automatically, and simplifies the component code.
<a routerLink="" routerLinkActive #rlaHome="routerLinkActive" [routerLinkActiveOptions]="{exact: true}" tabindex="-1">
<ix-menu-item [icon]="icons.iconHome" [active]="rlaHome.isActive">
Get Started
</ix-menu-item>
</a>
<a routerLink="forms" routerLinkActive #rlaForms="routerLinkActive" tabindex="-1">
<ix-menu-item [icon]="icons.iconTextDocument" [active]="rlaForms.isActive">
Forms
</ix-menu-item>
</a>
<a routerLink="charts" routerLinkActive #rlaCharts="routerLinkActive" tabindex="-1">
<ix-menu-item [icon]="icons.iconPiechart" [active]="rlaCharts.isActive">
Charts
</ix-menu-item>
</a>
<a routerLink="grids" routerLinkActive #rlaGrids="routerLinkActive" tabindex="-1">
<ix-menu-item [icon]="icons.iconTable" [active]="rlaGrids.isActive">
Grids
</ix-menu-item>
</a>
| import { CommonModule } from '@angular/common'; | ||
| import { Component } from '@angular/core'; | ||
| import { Router, RouterLink, RouterOutlet } from '@angular/router'; | ||
| import { | ||
| IxApplication, | ||
| IxApplicationHeader, | ||
| IxAvatar, | ||
| IxContent, | ||
| IxMenu, | ||
| IxMenuItem, | ||
| } from '@siemens/ix-angular/standalone'; | ||
| import { CompanyLogoComponent } from './../components/company-logo/company-logo.component'; | ||
| import { iconHome, iconPiechart, iconTable, iconTextDocument } from '@siemens/ix-icons/icons'; | ||
|
|
||
| @Component({ | ||
| selector: 'app-root', | ||
| imports: [ | ||
| CommonModule, | ||
| RouterOutlet, | ||
| RouterLink, | ||
| IxApplication, | ||
| IxApplicationHeader, | ||
| IxAvatar, | ||
| IxMenu, | ||
| IxMenuItem, | ||
| IxContent, | ||
| ], | ||
| templateUrl: './app.html', | ||
| styleUrl: './app.css' | ||
| }) | ||
| export class App { | ||
|
|
||
| readonly icons = { | ||
| iconHome, | ||
| iconTextDocument, | ||
| iconPiechart, | ||
| iconTable | ||
| } as const; | ||
|
|
||
| protected readonly companyLogoComponent = CompanyLogoComponent; | ||
|
|
||
| constructor(private router: Router) {} | ||
|
|
||
| isActiveRoute(path: string): boolean { | ||
| if (path === '/') { | ||
| return this.router.url === '/' || this.router.url === ''; | ||
| } | ||
| return this.router.url === path || this.router.url.startsWith(path + '/'); | ||
| } | ||
| } |
There was a problem hiding this comment.
With the adoption of routerLinkActive in the template, we can clean up the component by removing the Router dependency, the constructor, and the custom isActiveRoute method. We also need to import and add RouterLinkActive to the component's imports array.
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import {
IxApplication,
IxApplicationHeader,
IxAvatar,
IxContent,
IxMenu,
IxMenuItem,
} from '@siemens/ix-angular/standalone';
import { CompanyLogoComponent } from './../components/company-logo/company-logo.component';
import { iconHome, iconPiechart, iconTable, iconTextDocument } from '@siemens/ix-icons/icons';
@Component({
selector: 'app-root',
imports: [
CommonModule,
RouterOutlet,
RouterLink,
RouterLinkActive,
IxApplication,
IxApplicationHeader,
IxAvatar,
IxMenu,
IxMenuItem,
IxContent,
],
templateUrl: './app.html',
styleUrl: './app.css'
})
export class App {
readonly icons = {
iconHome,
iconTextDocument,
iconPiechart,
iconTable
} as const;
protected readonly companyLogoComponent = CompanyLogoComponent;
}| import { provideRouter } from '@angular/router'; | ||
| import { IxModule } from '@siemens/ix-angular'; | ||
|
|
||
| import { ApplicationConfig, provideZoneChangeDetection, ErrorHandler } from '@angular/core'; |
There was a problem hiding this comment.
| import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community'; | ||
| import { addIcons } from '@siemens/ix-icons'; | ||
| import { iconHome, iconPiechart, iconTextDocument, iconTable, iconQuestion } from '@siemens/ix-icons/icons'; |
There was a problem hiding this comment.
The imports for addIcons and the individual icons are unused in main.ts and can be safely removed.
| import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community'; | |
| import { addIcons } from '@siemens/ix-icons'; | |
| import { iconHome, iconPiechart, iconTextDocument, iconTable, iconQuestion } from '@siemens/ix-icons/icons'; | |
| import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community'; |
| onInspectionTypeChange(event: CustomEvent<string | string[]>) { | ||
| const value = event.detail; | ||
| this.inspectionType = Array.isArray(value) ? value[0] || '' : value; | ||
| } |
There was a problem hiding this comment.
To prevent potential runtime type issues or strict null check errors if event.detail is null or undefined, use a nullish coalescing operator to fall back to an empty string.
| onInspectionTypeChange(event: CustomEvent<string | string[]>) { | |
| const value = event.detail; | |
| this.inspectionType = Array.isArray(value) ? value[0] || '' : value; | |
| } | |
| onInspectionTypeChange(event: CustomEvent<string | string[]>) { | |
| const value = event.detail; | |
| this.inspectionType = Array.isArray(value) ? value[0] || '' : (value ?? ''); | |
| } |
| label="Inspection Type" | ||
| helper-text="Choose the inspection to perform" | ||
| :value="inspectionType" | ||
| @value-change="inspectionType = String($event.detail)" |
There was a problem hiding this comment.
Integrate new ix starter apps for angular, react and vue.