Upgrading to Angular version 20

Sterling Store Engagement is upgraded to Angular version 20. Make sure that you migrate your extensions to Angular version 20.

Note: If you cannot migrate to Angular version 20, but want to modify your extensions in Angular version 18, you can continue to build your customizations with the 26.1.1.2 - 10.0.2601.2 developer toolkit. To get the most recent features, enhancements, and fixes, you must upgrade to Angular version 20.
  • You must have Angular version 18 workspace from the 26.1.1.2 - 10.0.2601.2 or any Angular version 18 developer toolkit.
  • Ensure that you are on Node.js version 24.13.0.
The migration process involves two steps.
  1. Upgrade from Angular version 18 to 19.
  2. Upgrade from version 19 to 20.
Note: Ensure you run all commands from <WORKSPACE>/store-frontend-src folder.
  1. Run the following command to update Angular and related packages to version 19:
    ng update @angular/core@19 @angular/cli@19 @angular-builders/custom-webpack@19 @angular-devkit/schematics-cli@19 @angular-eslint/builder@19 @angular-eslint/eslint-plugin@19 @angular-eslint/eslint-plugin-template@19 @angular-eslint/schematics@19 @angular-eslint/template-parser@19 --force
  2. When prompted for optional migration, press the space bar to deselect the optional migrations. Then press Enter to continue.
  3. When the second prompt appears for the APP_INITIALIZER migration, press the space bar to select it. It is not selected by default. Then press Enter to start the migration.
  4. The APP_INITIALIZER migration adds an extra injector that must be removed. In all app.module.ts files in your extensions, search for provideAppInitializer and remove one extra LocalizationService injector.
    See the following existing code:
    const initializerFn = (LocalizationService.initializeTranslations)(
      inject(TranslateService), 
      inject(Injector), 
      inject(LocalizationService)
    );
    See the following code new code:
    const initializerFn = (LocalizationService.initializeTranslations)(
      inject(TranslateService), 
      inject(Injector)
    );
  5. If the following files are extended, apply these changes:
    1. First file: packages/libs/functional-components/src/lib/components/payment-method/credit-card/credit-card.component.ts.
      In the getBillingAddress method, the following illustrates the existing code:
      return { ...this.personInfoBillToForCC } || {};
      See the following code new code:
      return this.personInfoBillToForCC ? { ...this.personInfoBillToForCC } : {};
    2. Second file: packages/features/returns/src/app/features/returns/return-capture-wizard-page/return-list-page/exchange-line-list/exchange-line-list.component.ts.
      See the following existing code:
      this.orderLineList = { ...res?.Order?.OrderLines } || [];
      See the following new code:
      this.orderLineList = res?.Order?.OrderLines ? { ...res?.Order?.OrderLines } : {};
  6. Run the following command to update Angular and the related packages to version 20:
    ng update @angular/core@20 @angular/cli@20 @angular-builders/custom-webpack@20 @angular-devkit/schematics-cli@20 @angular-eslint/builder@20 @angular-eslint/eslint-plugin@20 @angular-eslint/eslint-plugin-template@20 @angular-eslint/schematics@20 @angular-eslint/template-parser@20
  7. Press the space bar to skip the optional migrations when prompted and press Enter to continue.
  8. A second prompt appears with more optional migrations. Press A to select all migrations and press enter to continue.
  9. If the following files are extended, apply the changes that are listed:
    1. First file: packages/features/dashboard/src/app/features/dashboard/dashboard-page/order-tasks-chart/order-tasks-chart.component.html
      See the following existing code:
      @for (task of taskData let i=index; track task)
      See the following new code:
      @for (task of taskData; track task; let i=$index)
    2. Second file: packages/features/pack-order/src/app/features/pack-order/pack-order-list-page/transfer-order/transfer-order.component.html
      See the following existing code:
      @for (shipment of shipmentList let i = index; track shipment)
      See the following new code:
      @for (shipment of shipmentList; track shipment; let i = $index)
  10. In each extension, update the ngx-translate configuration in the app.module.ts file.
    See the following existing code:
    this.translate.setDefaultLang('en');
    See the following new code:
    this.translate.setFallbackLang('en');
  11. In the most recent developer toolkit 26.2.4.0 - 10.0.2604.0, browse to the extensions/libs/styles directory, and copy the package.json file to your extension folder.
  12. Setup a new workspace from the most recent developer toolkit 26.2.4.0 - 10.0.2604.0 by completing the following steps:
    1. Copy the migrated extensions from the previous workspace to the new workspace.
    2. Rerun the following command by using an absolute path to test the extensions:
      yarn bootstrap
    3. Merge incoming changes from the application-provided code with extensions. This ensures that you are on the most recent version of the code and prevents compilation errors.
    4. Consider the next set of steps while you merge your changes.
  13. ng-bootstrap v19 introduces breaking changes that affect popover positioning. If the classes from the listed set of files are overridden, apply the following changes:
    1. File A: packages/features/receive-inventory/src/app/features/receive-inventory/shipment-list-page/modals/receiving-filter/receiving-filter.component.html. Locate the ngbPopover element and change the placement attribute.
      See the following existing code:
      <button ... [ngbPopover]="..." placement="bottom">
      See the following new code:
      <button ... [ngbPopover]="..." placement="bottom-end">
    2. File B: packages/features/receive-inventory/src/app/features/receive-inventory/shipment-list-page/modals/receiving-filter/receiving-filter.component.scss.
      If the .isf-receiving-filter class is overridden from this file, apply the following changes:
      1. Remove the following block entirely.
        .popover.bs-popover-bottom div.popover-arrow {
            left: 57%; 
        }
      2. Remove the margin-left from arrow::after.
        .popover.bs-popover-bottom div.popover-arrow::after {
            border-bottom-color: $blue;
            /* Remove: margin-left: 140px; */
        }
      3. Add mobile responsiveness.
        @include media-breakpoint-down(sm) {
            ngb-popover-window {
                display: none !important;
            }
        }
      4. Update the CSS selector from .popover.bs-popover-bottom to .popover.bs-popover-bottom-end.
        .popover.bs-popover-bottom-end div.popover-arrow::after {
            border-bottom-color: $blue;
        }
         
    3. File C: packages/libs/common-components/src/lib/components/filter-placeholder/filter-placeholder.component.scss.

      If the .isf-filter-placeholder class is overridden from this file, apply the following changes:

      1. Remove the following block entirely.
        .popover.bs-popover-bottom div.popover-arrow {
            left: 57%; 
        }
      2. Remove the margin-left from arrow::after.
        .popover.bs-popover-bottom div.popover-arrow::after {
            border-bottom-color: $blue;
            /* Remove: margin-left: 140px; */
        }
    4. File D: packages/libs/styles/src/styles/utilities/_override.scss.
      If the .isf-sort ngb-popover-window class is overridden from this file, remove the following:
      position: absolute;
      left: -100px !important;
      
      &.bs-popover-bottom .popover-arrow::before,
      &.bs-popover-bottom .popover-arrow::after {
          right: -100px;
      }
      If the .isf-filter ngb-popover-window class is overridden from this file, remove the following:
      position: absolute;
      left: -95px !important;
      
      &.bs-popover-bottom .popover-arrow::before,
      &.bs-popover-bottom .popover-arrow::after {
          right: -95px;
      }
      
      @include media-breakpoint-down(lg) {
          left: -120px !important;
          
          &.bs-popover-bottom .popover-arrow::before,
          &.bs-popover-bottom .popover-arrow::after {
              right: -120px;
          }
      }
      If the .isf-filter class is overridden from this file, remove the following:
      .popover.bs-popover-bottom div.popover-arrow {
          left: 88%; 
          @include media-breakpoint-down(lg) {
              left: 93%; 
          } 
      }
      If the .isf-related-task ngb-popover-window class is overridden from this file, remove the following:
      /* Change from: left: -84px !important; */
      /* Change to: */
      left: -28px !important;
      
      &.bs-popover-bottom .popover-arrow::before,
      &.bs-popover-bottom .popover-arrow::after {
          top: 1px;
          /* Change from: right: -77px; */
          /* Change to: */
          right: -21.5px;
      }
      
      @include media-breakpoint-down(lg) {
          /* Change from: left: -84px !important; */
          /* Change to: */
          left: -28px !important;
      }
       
      If the .isf-to-details-for-pr ngb-popover-window class is overridden from this file, remove the following:
      top: -13px !important; 
      left: 0px !important;
      If the .isf-receiving-filter ngb-popover-window class is overridden from this file, remove the following:
      left: -155px !important;
      If the .isf-filter-placeholder ngb-popover-window class is overridden from this file, remove the following:
      left: -155px !important;
  14. To start the application to test this upgrade, run the following command:
    yarn start-app
Note: If you use dev or qa cloud instance as a remote server for development purpose, you need to make the changes mentioned in Configuring local development server.