Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update title strategy service to get project name from localized text #19850

Merged
merged 6 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions docs/en/UI/Angular/Title-Strategy-Service.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Title Strategy For Angular

## **ABP has a default title strategy for Angular UI**.

This strategy is based on the title property. Provide a title property when setting a new route.

**Example**

```ts
{
path: 'customers',
component: CustomersComponent,
title: 'AbpCustomers::Roles'
},
```

- It is better to use localized text in the title property. It will be translated by **LocalizationService**.
- The **`title`** property is already set in **ABP internal packages**.

## How it looks

When you create a new route and provide a **`title`** property, it will look like this **`<title> | <projectName>`**

### What is `projectName` and How to Customize

- **`projectName`** is the name of your application. By default, ABP sets a [**`projectName`**](https://github.com/abpframework/abp/blob/f48f78618a326644843c01424b093f0d79448769/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain.Shared/Localization/MyProjectName/en.json#L4) for your application. This localization text is added for customization and can be changed for different languages.

### Disable `projectName`

- If you don't want to show **`projectName`** in the title, you can disable it.

**app.module.ts**

```ts
import { DISABLE_PROJECT_NAME } from '@abp/ng.core';

providers: [
...,
{ provide: DISABLE_PROJECT_NAME, useValue: true}
],
```

- Now only title will be shown.

## Override ABP's Default Title Strategy

**app.module.ts**

```ts
import { TitleStrategy } from '@angular/router';
import { YourCustomStrategy } from './title-strategy.service.ts';

providers: [
...,
{ provide: TitleStrategy, useExisting: YourCustomStrategy },
],
```

- You can check [Angular Documentation](https://angular.io/api/router/TitleStrategy) to write a custom **`TitleStrategy`**.
4 changes: 4 additions & 0 deletions docs/en/docs-nav.json
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,10 @@
{
"text": "Abp Window Service",
"path": "UI/Angular/Abp-Window-Service.md"
},
{
"text": "Title Strategy",
"path": "UI/Angular/Title-Strategy-Service.md"
}
]
},
Expand Down
17 changes: 10 additions & 7 deletions npm/ng-packs/packages/core/src/lib/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { ToInjectorPipe } from './pipes/to-injector.pipe';
import { CookieLanguageProvider } from './providers/cookie-language.provider';
import { LocaleProvider } from './providers/locale.provider';
import { LocalizationService } from './services/localization.service';
import { OTHERS_GROUP } from './tokens';
import { DISABLE_PROJECT_NAME, OTHERS_GROUP } from './tokens';
import { localizationContributor, LOCALIZATIONS } from './tokens/localization.token';
import { CORE_OPTIONS, coreOptionsFactory } from './tokens/options.token';
import { TENANT_KEY } from './tokens/tenant-key.token';
Expand All @@ -40,12 +40,11 @@ import { DefaultQueueManager } from './utils/queue';
import { IncludeLocalizationResourcesProvider } from './providers/include-localization-resources.provider';
import { SORT_COMPARE_FUNC, compareFuncFactory } from './tokens/compare-func.token';
import { AuthErrorFilterService } from './abstracts';
import { DYNAMIC_LAYOUTS_TOKEN } from "./tokens/dynamic-layout.token";
import { DEFAULT_DYNAMIC_LAYOUTS } from "./constants";
import { DYNAMIC_LAYOUTS_TOKEN } from './tokens/dynamic-layout.token';
import { DEFAULT_DYNAMIC_LAYOUTS } from './constants';
import { AbpTitleStrategy } from './services/title-strategy.service';
import { LocalStorageListenerService } from './services/local-storage-listener.service';


const standaloneDirectives = [
AutofocusDirective,
InputEventDebounceDirective,
Expand Down Expand Up @@ -201,12 +200,16 @@ export class CoreModule {
IncludeLocalizationResourcesProvider,
{
provide: DYNAMIC_LAYOUTS_TOKEN,
useValue: options.dynamicLayouts || DEFAULT_DYNAMIC_LAYOUTS
useValue: options.dynamicLayouts || DEFAULT_DYNAMIC_LAYOUTS,
},
{
provide: TitleStrategy,
useExisting: AbpTitleStrategy
}
useExisting: AbpTitleStrategy,
},
{
provide: DISABLE_PROJECT_NAME,
useValue: options.disableProjectNameInTitle || false,
},
],
};
}
Expand Down
1 change: 1 addition & 0 deletions npm/ng-packs/packages/core/src/lib/models/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export namespace ABP {
localizations?: Localization[];
othersGroup?: string;
dynamicLayouts?: Map<string, string>;
disableProjectNameInTitle?: boolean;
}

export interface Child {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@ 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 } from './config-state.service';
import { LocalizationService } from './localization.service';
import { DISABLE_PROJECT_NAME } from '../tokens';

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

projectName = toSignal(this.configState.getDeep$('localization.defaultResourceName'), {
initialValue: 'MyProjectName',
});
langugageChange = toSignal(this.localizationService.languageChange$);

constructor() {
Expand All @@ -30,14 +27,22 @@ export class AbpTitleStrategy extends TitleStrategy {

override updateTitle(routerState: RouterStateSnapshot) {
this.routerState = routerState;
let title = this.buildTitle(routerState);
const title = this.buildTitle(routerState);

const projectName = this.localizationService.instant({
key: '::AppName',
defaultValue: 'MyProjectName',
});

if (!title) {
this.title.setTitle(this.projectName());
return;
return this.title.setTitle(projectName);
}

let localizedText = this.localizationService.instant({ key: title, defaultValue: title });
if (!this.disableProjectName) {
localizedText += ` | ${projectName}`;
}

const localizedTitle = this.localizationService.instant({ key: title, defaultValue: title });
this.title.setTitle(`${localizedTitle} | ${this.projectName()}`);
this.title.setTitle(localizedText);
}
}
3 changes: 2 additions & 1 deletion npm/ng-packs/packages/core/src/lib/tokens/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export * from './check-authentication-state';
export * from './http-context.token';
export * from './others-group.token';
export * from './tenant-not-found-by-name';
export * from './compare-func.token'
export * from './compare-func.token';
export * from './title-strategy-disable-project-name.token';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { InjectionToken } from '@angular/core';

export const DISABLE_PROJECT_NAME = new InjectionToken<boolean>('DISABLE_APP_NAME');
22 changes: 11 additions & 11 deletions templates/module/angular/projects/dev-app/src/index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DevApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
<head>
<meta charset="utf-8" />
<title>MyProjectName</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<app-root></app-root>
</body>
</html>
Loading