From 862aa9d4bac057b63104039cf5f93947730917fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=A1=E8=89=B2?= Date: Sun, 25 Nov 2018 16:35:24 +0800 Subject: [PATCH] fix(module:page-header): should be clean old breadcrumb data when changes (#296) * fix(module:page-header): should be clean old breadcrumb data when changes * chore: refactor code * fix: refresh title when router changed - close #293 * test: add unit test --- .../page-header/page-header.component.html | 4 +- .../abc/page-header/page-header.component.ts | 55 ++++++++++--------- packages/abc/page-header/page-header.spec.ts | 23 +++++++- src/app/routes/dev/home/home.component.ts | 5 +- src/app/routes/dev/layout.component.html | 7 ++- src/app/routes/dev/layout.component.ts | 19 +++++-- src/app/routes/dev/pages/page.component.ts | 5 +- 7 files changed, 83 insertions(+), 35 deletions(-) diff --git a/packages/abc/page-header/page-header.component.html b/packages/abc/page-header/page-header.component.html index d834d5075b..1241c78308 100644 --- a/packages/abc/page-header/page-header.component.html +++ b/packages/abc/page-header/page-header.component.html @@ -22,8 +22,8 @@
-

- {{_title}} +

+ {{_titleVal}}

diff --git a/packages/abc/page-header/page-header.component.ts b/packages/abc/page-header/page-header.component.ts index e5498fd2b6..c6afa65eb3 100644 --- a/packages/abc/page-header/page-header.component.ts +++ b/packages/abc/page-header/page-header.component.ts @@ -2,7 +2,6 @@ import { Component, Input, TemplateRef, - ContentChild, OnInit, OnChanges, Inject, @@ -15,7 +14,7 @@ import { } from '@angular/core'; import { Router, RouterEvent, NavigationEnd } from '@angular/router'; import { NzAffixComponent } from 'ng-zorro-antd'; -import { Subscription } from 'rxjs'; +import { Subscription, Observable, merge } from 'rxjs'; import { filter } from 'rxjs/operators'; import { isEmpty, InputBoolean, InputNumber } from '@delon/util'; @@ -39,9 +38,8 @@ import { PageHeaderConfig } from './page-header.config'; export class PageHeaderComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy { private inited = false; - private i18n$: Subscription; + private ref$: Subscription; private set$: Subscription; - private routerEvent$: Subscription; @ViewChild('conTpl') private conTpl: ElementRef; @ViewChild('affix') @@ -52,11 +50,16 @@ export class PageHeaderComponent if (this._menus) { return this._menus; } - this._menus = this.menuSrv.getPathByUrl(this.router.url.split('?')[0], this.recursiveBreadcrumb); + this._menus = this.menuSrv.getPathByUrl( + this.router.url.split('?')[0], + this.recursiveBreadcrumb, + ); return this._menus; } + _titleVal: string; + // #region fields _title: string; @@ -69,6 +72,7 @@ export class PageHeaderComponent } else { this._title = value; } + this._titleVal = this._title; } @Input() @@ -160,9 +164,6 @@ export class PageHeaderComponent private reuseSrv: ReuseTabService, ) { Object.assign(this, cog); - if (this.i18nSrv) { - this.i18n$ = this.i18nSrv.change.subscribe(() => this.refresh()); - } this.set$ = settings.notify .pipe( filter( @@ -170,16 +171,19 @@ export class PageHeaderComponent ), ) .subscribe(() => this.affix.updatePosition({})); - this.routerEvent$ = this.router.events - .pipe( - filter((event: RouterEvent) => event instanceof NavigationEnd) - ) - .subscribe( - (event: RouterEvent) => { - this._menus = null; - this.refresh(); - } - ); + + const data$: Observable[] = [ + this.router.events.pipe( + filter((event: RouterEvent) => event instanceof NavigationEnd), + ), + ]; + if (this.i18nSrv) { + data$.push(this.i18nSrv.change); + } + this.ref$ = merge(...data$).subscribe(() => { + this._menus = null; + this.refresh(); + }); } refresh() { @@ -187,8 +191,10 @@ export class PageHeaderComponent } private genBreadcrumb() { - if (this.breadcrumb || !this.autoBreadcrumb || this.menus.length <= 0) + if (this.breadcrumb || !this.autoBreadcrumb || this.menus.length <= 0) { + this.paths = []; return; + } const paths: any[] = []; this.menus.forEach(item => { if (typeof item.hideInBreadcrumb !== 'undefined' && item.hideInBreadcrumb) @@ -222,15 +228,15 @@ export class PageHeaderComponent const item = this.menus[this.menus.length - 1]; let title = item.text; if (item.i18n && this.i18nSrv) title = this.i18nSrv.fanyi(item.i18n); - this._title = title; + this._titleVal = title; } - if (this._title && this.syncTitle) { + if (this._titleVal && this.syncTitle) { if (this.titleSrv) { - this.titleSrv.setTitle(this._title); + this.titleSrv.setTitle(this._titleVal); } if (this.reuseSrv) { - this.reuseSrv.title = this._title; + this.reuseSrv.title = this._titleVal; } } @@ -259,8 +265,7 @@ export class PageHeaderComponent } ngOnDestroy(): void { - if (this.i18n$) this.i18n$.unsubscribe(); this.set$.unsubscribe(); - this.routerEvent$.unsubscribe(); + this.ref$.unsubscribe(); } } diff --git a/packages/abc/page-header/page-header.spec.ts b/packages/abc/page-header/page-header.spec.ts index 63452372eb..85c3cbfd1f 100644 --- a/packages/abc/page-header/page-header.spec.ts +++ b/packages/abc/page-header/page-header.spec.ts @@ -1,5 +1,5 @@ import { Component, DebugElement, ViewChild, Injector } from '@angular/core'; -import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing'; +import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { Router } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; @@ -225,6 +225,27 @@ describe('abc: page-header', () => { expect(dl.queryAll(By.css('.custom-title')).length).toBe(1); }); + it('should be refresh title when route changed of auto generate title', fakeAsync(() => { + genModule({ created: false }); + context.title = undefined; + context.autoTitle = true; + menuSrv.add([ + { text: '1', link: '/1-1/p1' }, + { text: '2', link: '/1-1/p2' }, + ]); + const urlSpy = spyOnProperty(router, 'url'); + urlSpy.and.returnValue('/1-1/p1'); + tick(); + fixture.detectChanges(); + checkValue('.page-header__title', '1'); + + urlSpy.and.returnValue('/1-1/p2'); + router.navigateByUrl('/1-1/p2'); + tick(); + fixture.detectChanges(); + checkValue('.page-header__title', '2'); + })); + describe('[generateion title]', () => { beforeEach(() => { genModule({ diff --git a/src/app/routes/dev/home/home.component.ts b/src/app/routes/dev/home/home.component.ts index cab5f8e478..3e9b1aa952 100644 --- a/src/app/routes/dev/home/home.component.ts +++ b/src/app/routes/dev/home/home.component.ts @@ -2,7 +2,10 @@ import { Component } from '@angular/core'; @Component({ selector: 'dev-home', - template: `home` + template: ` + + home + ` }) export class DevHomeComponent { diff --git a/src/app/routes/dev/layout.component.html b/src/app/routes/dev/layout.component.html index 760d355a81..f00a082504 100644 --- a/src/app/routes/dev/layout.component.html +++ b/src/app/routes/dev/layout.component.html @@ -1,6 +1,6 @@
diff --git a/src/app/routes/dev/layout.component.ts b/src/app/routes/dev/layout.component.ts index 91779d425c..04de17aee9 100644 --- a/src/app/routes/dev/layout.component.ts +++ b/src/app/routes/dev/layout.component.ts @@ -1,5 +1,5 @@ -import { Component, OnInit, HostBinding } from '@angular/core'; -import { MenuService, SettingsService, Menu } from '@delon/theme'; +import { Component, OnInit, HostBinding, Inject } from '@angular/core'; +import { MenuService, SettingsService, Menu, ALAIN_I18N_TOKEN } from '@delon/theme'; import { NzMessageService, NzIconService } from 'ng-zorro-antd'; // #region icons @@ -22,6 +22,7 @@ import { GithubOutline, AppstoreOutline, } from '@ant-design/icons-angular/icons'; +import { I18NService, LangType } from 'app/core/i18n/service'; const ICONS = [ MenuFoldOutline, @@ -66,6 +67,8 @@ export class DevLayoutComponent implements OnInit { return this.settings.layout.collapsed; } + lang: LangType = 'zh-CN'; + menus: Menu[] = [ { text: 'test', @@ -73,8 +76,9 @@ export class DevLayoutComponent implements OnInit { children: [ { text: 'Dashboard', - link: '/', + link: '/dev', icon: 'anticon anticon-dashboard', + i18n: 'app.header.menu.home', badge: 5, }, { @@ -97,7 +101,7 @@ export class DevLayoutComponent implements OnInit { text: 'ABC', icon: 'anticon anticon-appstore', children: [ - { text: 'Reuse Tab7', link: '/dev/l1' }, + { text: 'Reuse Tab7', link: '/dev/l1', i18n: 'app.header.menu.docs' }, { text: 'Reuse Tab6', link: '/dev/l2' }, { text: 'Reuse Tab5', link: '/dev/l3' }, { text: 'Reuse Tab4', link: '/dev/l4' }, @@ -116,6 +120,8 @@ export class DevLayoutComponent implements OnInit { private menuSrv: MenuService, public settings: SettingsService, public msgSrv: NzMessageService, + @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService + ) { iconSrv.addIcon(...ICONS); } @@ -124,6 +130,11 @@ export class DevLayoutComponent implements OnInit { this.settings.setLayout('collapsed', !this.settings.layout.collapsed); } + toggleLang() { + this.lang = this.lang === 'zh-CN' ? 'en-US' : 'zh-CN'; + this.i18n.use(this.lang); + } + ngOnInit(): void { this.menuSrv.add(this.menus); } diff --git a/src/app/routes/dev/pages/page.component.ts b/src/app/routes/dev/pages/page.component.ts index 2d7593f07e..3d1d305bc6 100644 --- a/src/app/routes/dev/pages/page.component.ts +++ b/src/app/routes/dev/pages/page.component.ts @@ -3,7 +3,10 @@ import { ActivatedRoute } from '@angular/router'; @Component({ selector: 'dev-page', - template: `page: {{ router.url | json }}` + template: ` + + page: {{ router.url | json }} + ` }) export class DevPageComponent { constructor(public router: ActivatedRoute) {