Skip to content

Commit

Permalink
SEO support async config #9951
Browse files Browse the repository at this point in the history
  • Loading branch information
PowerKiKi committed Nov 10, 2023
1 parent b19380e commit 7f69a2c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {RouterTestingModule} from '@angular/router/testing';
import {Component} from '@angular/core';
import {Router, Routes} from '@angular/router';
import {Meta, Title} from '@angular/platform-browser';
import {of} from 'rxjs';

@Component({
template: ` <div>Test simple component</div>`,
Expand Down Expand Up @@ -307,4 +308,23 @@ describe('NaturalSeoService', () => {
);
});
});

describe('with async config', () => {
beforeEach(async () => {
await configure(
of(
{
applicationName: 'my app 1',
},
{
applicationName: 'my app 2',
},
),
);
});

it('should update SEO with latest available app name', async () => {
await assertSeo('no-seo', null, 'my app 2', undefined, undefined);
});
});
});
23 changes: 16 additions & 7 deletions projects/natural/src/lib/modules/common/services/seo.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import {DOCUMENT} from '@angular/common';
import {Inject, Injectable, InjectionToken, LOCALE_ID} from '@angular/core';
import {Meta, Title} from '@angular/platform-browser';
import {ActivatedRouteSnapshot, Data, NavigationEnd, PRIMARY_OUTLET, Router} from '@angular/router';
import {filter} from 'rxjs/operators';
import {filter, startWith} from 'rxjs/operators';
import {NaturalDialogTriggerComponent} from '../../dialog-trigger/dialog-trigger.component';
import {combineLatest, Observable, of} from 'rxjs';

export type NaturalSeo = NaturalSeoBasic | NaturalSeoCallback | NaturalSeoResolve;

Expand Down Expand Up @@ -81,7 +82,7 @@ interface Robots {
robots?: string;
}

export interface NaturalSeoConfig {
interface NaturalSeoConfigPlain {
/**
* The name of the application that will always appear in the page title
*/
Expand Down Expand Up @@ -113,6 +114,7 @@ export interface NaturalSeoConfig {
readonly languages?: Readonly<string[]>;
}

export type NaturalSeoConfig = NaturalSeoConfigPlain | Observable<NaturalSeoConfigPlain>;
export const NATURAL_SEO_CONFIG = new InjectionToken<NaturalSeoConfig>('Configuration for SEO service');

export function stripTags(str: string): string {
Expand Down Expand Up @@ -146,16 +148,23 @@ type ResolvedData = {
})
export class NaturalSeoService {
private routeData?: Data;
private config: NaturalSeoConfigPlain = {
applicationName: '',
};

public constructor(
@Inject(NATURAL_SEO_CONFIG) private readonly config: NaturalSeoConfig,
@Inject(NATURAL_SEO_CONFIG) configToken: NaturalSeoConfig,
private readonly router: Router,
private readonly titleService: Title,
private readonly metaTagService: Meta,
@Inject(DOCUMENT) private readonly document: Document,
@Inject(LOCALE_ID) private locale: string,
) {
this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
combineLatest({
config: configToken instanceof Observable ? configToken.pipe(startWith(this.config)) : of(configToken),
navigationEnd: this.router.events.pipe(filter(event => event instanceof NavigationEnd)),
}).subscribe(({config}) => {
this.config = config;
const root = this.router.routerState.root.snapshot;
this.routeData = this.getRouteData(root);

Expand All @@ -179,11 +188,11 @@ export class NaturalSeoService {
/**
* Update the SEO with given info. The extra part and app name will be appended automatically.
*
* In most cases this should not be used, and instead the SEO should be configured in the routing,
* In most cases, this should not be used. And instead, the SEO should be configured in the routing,
* possibly with the callback variant for some dynamism.
*
* But in rare cases only the Component is able to build a proper page title, after it gather everything it
* needed. For those cases the Component can inject this service and update the SEO directly.
* But in rare cases, only the Component is able to build a proper page title, after it gathered everything it
* needed. For those cases, the Component can inject this service and update the SEO directly.
*/
public update(seo: NaturalSeoBasic): void {
// Title
Expand Down

0 comments on commit 7f69a2c

Please sign in to comment.