Skip to content

Conversation

@PieterjanDeClippel
Copy link
Member

No description provided.

@gemini-code-assist
Copy link

Summary of Changes

Hello @PieterjanDeClippel, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request performs a comprehensive upgrade of the project to Angular 21. It involves significant refactoring to align with the latest Angular practices, including adjustments to standalone component usage, a move towards direct component imports over NgModules, and the adoption of Angular Signals for reactive programming. The changes also address compatibility issues with host bindings in Angular 21.

Highlights

  • Angular 21 Upgrade: The project has been upgraded to Angular 21, including updates to core Angular packages and several related libraries like @mintplayer/ng-animations, @mintplayer/ng-bootstrap, and @mintplayer/ng-swiper.
  • Standalone Component Refactoring: Many components and directives across the ng-bootstrap-demo application and mintplayer-ng-bootstrap libraries have had their standalone property removed or adjusted, indicating a shift in how standalone components are declared or integrated.
  • Module to Direct Import Conversion: Numerous *Module imports (e.g., BsGridModule, BsAlertModule) have been replaced with direct imports of individual components and directives (e.g., BsGridComponent, BsGridRowDirective, BsAlertComponent, BsAlertCloseComponent), reflecting a more granular import strategy.
  • Angular Signals Adoption: The reactivity model has been updated in several components, replacing BehaviorSubject and Observable patterns with Angular's new signal, computed, and effect primitives for state management and side effects.
  • Async Host Bindings Deprecation: The provideAsyncHostBindings() functionality has been commented out and related code removed, with a note indicating that Angular 21 now validates bindings, making previous async host binding patterns unsupported by default.
  • Dependency Injection Modernization: Dependency injection has been modernized in several places, utilizing the inject() function for services and injection tokens, such as the newly introduced GIT_REPO.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@nx-cloud
Copy link

nx-cloud bot commented Nov 23, 2025

View your CI Pipeline Execution ↗ for commit 45b9a63


☁️ Nx Cloud last updated this comment at 2025-11-24 08:27:17 UTC

@nx-cloud
Copy link

nx-cloud bot commented Nov 23, 2025

View your CI Pipeline Execution ↗ for commit e340b2f


☁️ Nx Cloud last updated this comment at 2025-11-23 20:18:04 UTC

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request appears to be a major refactoring effort to upgrade to Angular 21 and adopt standalone components. Many changes, such as migrating to the Signals API, updating dependencies, and moving from NgModules to standalone component imports, are positive steps. However, there's a critical and widespread issue: standalone: true has been removed from numerous components, yet they retain the imports property. In Angular, a component can only have an imports property if it is marked as standalone: true. Without this flag, the application will fail to compile. This needs to be rectified across all affected components. Given the PR's title and other changes, it seems the intention was to use standalone components, so standalone: true should likely be added back. I've added a specific comment on app.component.ts as an example of this issue. Additionally, I've noted some minor issues regarding the removal of private modifiers and changes to host listeners.

templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
standalone: true,
imports: [RouterOutlet, RouterLink, BsNavbarModule, NavbarRouterLinkActiveDirective],

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The standalone: true flag has been removed from the AppComponent, but it still has an imports array. A component can only use the imports array if it is a standalone component. Since this is the root component of a standalone application, it must have standalone: true. Please add standalone: true back. This issue is present in many other components in this PR.

Suggested change
imports: [RouterOutlet, RouterLink, BsNavbarModule, NavbarRouterLinkActiveDirective],
standalone: true,
imports: [RouterOutlet, RouterLink, BsNavbarModule, NavbarRouterLinkActiveDirective],
Comment on lines 12 to 21
constructor() {
this.example$
.pipe(map(example => deepClone(example, true, [Object])))
// .pipe(map((clone) => JSON.stringify(clone)))
.pipe(takeUntilDestroyed())
.subscribe(console.log);
effect(() => {
const example = this.example();
if (example === null) {
return;
}
const clone = deepClone(example, true, [Object]);
console.log(clone);
});
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic has been updated to use an effect with signals, which is great for reactivity. However, the console.log is probably for debugging and should be removed before merging.

Comment on lines +6 to +28
// @Component({
// selector: "demo-hello",
// template: `Hello {{ name }}!`,
//
// schemas: [CUSTOM_ELEMENTS_SCHEMA],
// imports: [],
// })
// export class HelloComponent {
// @Input() name!: string;

@HostBinding('class.d-inline-block')
@HostBinding('class.border')
@HostBinding('class.mw-100')
classes = true;
// @HostBinding('class.d-inline-block')
// @HostBinding('class.border')
// @HostBinding('class.mw-100')
// classes = true;

@HostBinding("$.style.padding.px")
@HostListener("$.style.padding.px")
readonly test = interval(1000).pipe(tap(console.log));
// @HostBinding("$.style.padding.px")
// @HostListener("$.style.padding.px")
// readonly test = interval(1000).pipe(tap(console.log));

@HostBinding("$.class.fw-bold")
@HostListener("$.class.fw-bold")
readonly active = this.test.pipe(map(v => v % 2));
}
// @HostBinding("$.class.fw-bold")
// @HostListener("$.class.fw-bold")
// readonly active = this.test.pipe(map(v => v % 2));
// }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The HelloComponent and its related async host bindings have been commented out. Since async host bindings are no longer supported in Angular 21, this is the correct approach to avoid compilation errors. However, it would be better to completely remove the dead code instead of just commenting it out to keep the codebase clean.

Comment on lines +15 to +25
canExit = () => {
if (this.allowExit === true) {
sub.next(true);
return true;
} else {
if (confirm(this.navigationLock.exitMessage ?? 'Are you sure you want to leave this page?')) {
sub.next(true);
return true;
} else {
sub.next(false);
return false;
}
}
});
// canExit = () => {
// if (this.allowExit === true) {
// return true;
// } else {
// if (confirm(this.navigationLock.exitMessage ?? 'Are you sure you want to leave this page?')) {
// return true;
// } else {
// return false;
// }
// }
// };
};

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The implementation of canExit has been changed from an Observable to a function. This is a significant API change. While the new implementation is valid, ensure this change is intentional and all call sites are updated accordingly. The previous implementation using Observable was also valid and might offer more flexibility in some scenarios.

@HostBinding('class.d-block')
@HostBinding('class.overflow-hidden')
private progressClass = true;
progressClass = true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The private modifier was removed from progressClass. If this property is not intended to be used from outside the component, it's good practice to keep it private to maintain proper encapsulation.

Suggested change
progressClass = true;
private progressClass = true;


@HostListener('window:blur') private onBlur() {
@HostListener('window:blur') onBlur() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The private modifier was removed from the onBlur method. If this method is not intended to be called from outside the directive, it should be kept private to encapsulate the directive's internal logic.

Suggested change
@HostListener('window:blur') onBlur() {
@HostListener('window:blur') private onBlur() {
//#endregion

@HostListener('window:blur') private onBlur() {
@HostListener('window:blur') onBlur() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The private modifier was removed from the onBlur method. If this method is not intended to be called from outside the directive, it should be kept private to encapsulate the directive's internal logic.

Suggested change
@HostListener('window:blur') onBlur() {
@HostListener('window:blur') private onBlur() {

@HostListener('document:keydown', ['$event'])
private onKeyDown(ev: KeyboardEvent) {
onKeyDown(ev: KeyboardEvent) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The private modifier was removed from the onKeyDown method. If this method is not intended to be called from outside the component, it should be kept private to encapsulate the component's internal logic.

Suggested change
onKeyDown(ev: KeyboardEvent) {
private onKeyDown(ev: KeyboardEvent) {
private overlayRef: OverlayRef | null = null;

@HostListener('window:blur') private onBlur() {
@HostListener('window:blur') onBlur() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The private modifier was removed from the onBlur method. If this method is not intended to be called from outside the directive, it should be kept private to encapsulate the directive's internal logic.

Suggested change
@HostListener('window:blur') onBlur() {
@HostListener('window:blur') private onBlur() {
@HostListener('document:keydown.ArrowRight', ['$event'])
@HostListener('document:keydown.ArrowUp', ['$event'])
@HostListener('document:keydown.ArrowDown', ['$event'])
@HostListener('document:keydown', ['$event'])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The @HostListeners for specific arrow keys have been replaced with a single listener for keydown. While this works, it's less efficient as it will trigger on every keydown event, not just the ones it's interested in. It's better to keep the more specific listeners for performance reasons.

 @HostListener('document:keydown.ArrowLeft', ['$event']) @HostListener('document:keydown.ArrowRight', ['$event']) @HostListener('document:keydown.ArrowUp', ['$event']) @HostListener('document:keydown.ArrowDown', ['$event']) onKeyPress(ev: KeyboardEvent) {
@PieterjanDeClippel PieterjanDeClippel marked this pull request as draft November 24, 2025 08:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants