abp icon indicating copy to clipboard operation
abp copied to clipboard

Angular: bad AbpTitleStrategy implementation

Open antonGritsenko opened this issue 9 months ago • 9 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Description

The AbpTitleStrategy have very weird implementation: it takes page title from the localization.defaultResourceName configuration, which is totally internal and always quite ugly. From the docs"

defaultResourceName can be set to change the default localization resource

Reproduction Steps

  1. Open angular page
  2. Check the title, it equal to default name of the resource used for localization

Expected behavior

Title is not ugly

Actual behavior

Title is ugly and can't be changed

Regression?

Yes (this is new in v8)

Known Workarounds

No

Version

8.1.1

User Interface

Angular

Database Provider

EF Core (Default)

Tiered or separate authentication server

Tiered

Operation System

Windows (Default)

Other information

No response

antonGritsenko avatar May 13 '24 22:05 antonGritsenko

@Sinan997 what's the point of this: https://github.com/abpframework/abp/blob/25ea951f0a3ea639e61a9c5c8c5d766b236cfd07/npm/ng-packs/packages/core/src/lib/services/title-strategy.service.ts#L17C52-L17C86 ?

antonGritsenko avatar May 13 '24 22:05 antonGritsenko

Hi @antonGritsenko, this is ABP internal title strategy. It merges page name and project name and bind it to the title.

For example if you create a project named CarStore and you are in Roles page it will look like this -> Roles | CarStore.

If you didn't like this strategy you can create your own strategy.

An example of creating custom TitleStrategy and override abp default strategy.

@Injectable({
  providedIn: 'root',
})
export class myCustomTitleStrategy extends TitleStrategy {
  constructor(private readonly title: Title) {
    super();
  }

  override updateTitle(routerState: RouterStateSnapshot) {
    const title = this.buildTitle(routerState);
    if (title !== undefined) {
      this.title.setTitle("My custom name");
    }
  }
}

app.module

providers: [{ provide: TitleStrategy, useClass: myCustomTitleStrategy }],

Sinan997 avatar May 14 '24 06:05 Sinan997

Yeah, but what's the point of such stratagy? 100% devs will change it because it useless. Why not to use same as you did on home page, just use localization?

antonGritsenko avatar May 14 '24 07:05 antonGritsenko

I dont think this is useless, it just adds <pageName> | . Adding page information to the title is a good practice instead of making the title of all pages the same.

Sinan997 avatar May 14 '24 07:05 Sinan997

Yeah, first part is great, I'm talking about second part :)

antonGritsenko avatar May 14 '24 07:05 antonGritsenko

Hi, @antonGritsenko so you are saying that the project name shouldn't exist in title. It should be only Roles Users etc?

Sinan997 avatar May 14 '24 07:05 Sinan997

I'm talking about that project name is ugly. Usually it have no spaces, but contains several words. Will be great to use page title | app title where app title is also localized string.

antonGritsenko avatar May 14 '24 08:05 antonGritsenko

Here is what I meant:

import { Injectable, effect, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { TitleStrategy, RouterStateSnapshot } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { ConfigStateService, LocalizationService } from '@abp/ng.core';


@Injectable({
  providedIn: 'root',
})
export class AbpTitleStrategy extends TitleStrategy {
  protected readonly title = inject(Title);
  protected readonly configState = inject(ConfigStateService);
  protected readonly localizationService = inject(LocalizationService);
  protected routerState: RouterStateSnapshot;

  langugageChange = toSignal(this.localizationService.languageChange$);

  constructor() {
    super();
    effect(() => {
      if (this.langugageChange()) {
        this.updateTitle(this.routerState);
      }
    });
  }

  override updateTitle(routerState: RouterStateSnapshot) {
    this.routerState = routerState;
    let title = this.buildTitle(routerState);
    const projectName = this.localizationService.instant({ key: "::AppTitle", defaultValue: "MyProjectName" });
    if (!title) {
      this.title.setTitle(projectName);
      return;
    }

    const localizedTitle = this.localizationService.instant({ key: title, defaultValue: title });
    this.title.setTitle(`${localizedTitle} | ${projectName}`);
  }
}

antonGritsenko avatar May 14 '24 20:05 antonGritsenko

Hi @antonGritsenko thank you for your feedback. https://github.com/abpframework/abp/issues/19834

Sinan997 avatar May 16 '24 08:05 Sinan997