Skip to content

Commit

Permalink
feat(module:anchor): sync new properties (#7494)
Browse files Browse the repository at this point in the history
  • Loading branch information
buqiyuan committed Jul 25, 2022
1 parent f423850 commit 254b429
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 7 deletions.
10 changes: 9 additions & 1 deletion components/anchor/anchor-link.component.ts
Expand Up @@ -27,7 +27,14 @@ import { NzAnchorComponent } from './anchor.component';
exportAs: 'nzLink',
preserveWhitespaces: false,
template: `
<a #linkTitle (click)="goToClick($event)" href="{{ nzHref }}" class="ant-anchor-link-title" title="{{ titleStr }}">
<a
#linkTitle
class="ant-anchor-link-title"
[href]="nzHref"
[title]="titleStr"
[target]="nzTarget"
(click)="goToClick($event)"
>
<span *ngIf="titleStr; else titleTpl || nzTemplate">{{ titleStr }}</span>
</a>
<ng-content></ng-content>
Expand All @@ -37,6 +44,7 @@ import { NzAnchorComponent } from './anchor.component';
})
export class NzAnchorLinkComponent implements OnInit, OnDestroy {
@Input() nzHref = '#';
@Input() nzTarget?: string;

titleStr: string | null = '';
titleTpl?: TemplateRef<NzSafeAny>;
Expand Down
37 changes: 31 additions & 6 deletions components/anchor/anchor.component.ts
Expand Up @@ -92,15 +92,23 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
@WithConfig<number>()
nzOffsetTop?: number = undefined;

@Input()
@InputNumber(undefined)
@WithConfig<number>()
nzTargetOffset?: number = undefined;

@Input() nzContainer?: string | HTMLElement;
@Input() nzCurrentAnchor?: string;

@Output() readonly nzClick = new EventEmitter<string>();
@Output() readonly nzChange = new EventEmitter<string>();
@Output() readonly nzScroll = new EventEmitter<NzAnchorLinkComponent>();

visible = false;
wrapperStyle: NgStyleInterface = { 'max-height': '100vh' };

container?: HTMLElement | Window;
activeLink?: string;

private links: NzAnchorLinkComponent[] = [];
private animating = false;
Expand Down Expand Up @@ -160,7 +168,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
}

const sections: Section[] = [];
const scope = (this.nzOffsetTop || 0) + this.nzBounds;
const offsetTop = this.nzTargetOffset ? this.nzTargetOffset : this.nzOffsetTop || 0;
const scope = offsetTop + this.nzBounds;
this.links.forEach(comp => {
const sharpLinkMatch = sharpMatcherRegx.exec(comp.nzHref.toString());
if (!sharpLinkMatch) {
Expand Down Expand Up @@ -195,11 +204,23 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
});
}

private setActive(comp?: NzAnchorLinkComponent): void {
const originalActiveLink = this.activeLink;
const targetComp = (this.nzCurrentAnchor && this.links.find(n => n.nzHref === this.nzCurrentAnchor)) || comp;
if (!targetComp) return;

targetComp.setActive();
const linkNode = targetComp.getLinkTitleElement();
this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
this.activeLink = (comp || targetComp).nzHref;
if (originalActiveLink !== this.activeLink) {
this.nzChange.emit(this.activeLink);
}
}

private handleActive(comp: NzAnchorLinkComponent): void {
this.clearActive();
comp.setActive();
const linkNode = comp.getLinkTitleElement();
this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
this.setActive(comp);
this.visible = true;
this.setVisible();
this.nzScroll.emit(comp);
Expand All @@ -226,7 +247,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
this.animating = true;
const containerScrollTop = this.scrollSrv.getScroll(this.getContainer());
const elOffsetTop = getOffsetTop(el, this.getContainer());
const targetScrollTop = containerScrollTop + elOffsetTop - (this.nzOffsetTop || 0);
let targetScrollTop = containerScrollTop + elOffsetTop;
targetScrollTop -= this.nzTargetOffset !== undefined ? this.nzTargetOffset : this.nzOffsetTop || 0;
this.scrollSrv.scrollTo(this.getContainer(), targetScrollTop, {
callback: () => {
this.animating = false;
Expand All @@ -237,7 +259,7 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
}

ngOnChanges(changes: SimpleChanges): void {
const { nzOffsetTop, nzContainer } = changes;
const { nzOffsetTop, nzContainer, nzCurrentAnchor } = changes;
if (nzOffsetTop) {
this.wrapperStyle = {
'max-height': `calc(100vh - ${this.nzOffsetTop}px)`
Expand All @@ -248,5 +270,8 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
this.container = typeof container === 'string' ? this.doc.querySelector(container) : container;
this.registerScrollEvent();
}
if (nzCurrentAnchor) {
this.setActive();
}
}
}
43 changes: 43 additions & 0 deletions components/anchor/anchor.spec.ts
Expand Up @@ -26,6 +26,7 @@ describe('anchor', () => {
fixture.detectChanges();
page = new PageObject();
spyOn(context, '_scroll');
spyOn(context, '_change');
srv = TestBed.inject(NzScrollService);
});
afterEach(() => context.comp.ngOnDestroy());
Expand Down Expand Up @@ -131,6 +132,18 @@ describe('anchor', () => {
});
});

describe('[nzCurrentAnchor]', () => {
it('customize the anchor highlight', () => {
context.nzCurrentAnchor = '#basic';
fixture.detectChanges();
const linkList = dl.queryAll(By.css('.ant-anchor-link'));
expect(linkList.length).toBeGreaterThan(0);
const activeLink = linkList.find(n => (n.nativeElement as HTMLDivElement).getAttribute('nzhref') === '#basic')!;
expect(activeLink).toBeTruthy();
expect((activeLink.nativeElement as HTMLDivElement).classList).toContain('ant-anchor-link-active');
});
});

describe('[nzShowInkInFixed]', () => {
beforeEach(() => {
context.nzAffix = false;
Expand Down Expand Up @@ -169,6 +182,30 @@ describe('anchor', () => {
});
});

describe('(nzChange)', () => {
it('should emit nzChange when click a link', fakeAsync(() => {
spyOn(srv, 'scrollTo').and.callFake((_containerEl, _targetTopValue = 0, options = {}) => {
if (options.callback) {
options.callback();
}
});
expect(context._change).not.toHaveBeenCalled();
page.to('#basic-target');
expect(context._change).toHaveBeenCalled();
}));
it('should emit nzChange when scrolling to the anchor', (done: () => void) => {
spyOn(context, '_change');
expect(context._change).not.toHaveBeenCalled();
page.scrollTo();
setTimeout(() => {
const inkNode = page.getEl('.ant-anchor-ink-ball');
expect(+inkNode.style.top!.replace('px', '')).toBeGreaterThan(0);
expect(context._change).toHaveBeenCalled();
done();
}, throttleTime);
});
});

it('(nzClick)', () => {
spyOn(context, '_click');
expect(context._click).not.toHaveBeenCalled();
Expand Down Expand Up @@ -233,9 +270,12 @@ describe('anchor', () => {
[nzBounds]="nzBounds"
[nzShowInkInFixed]="nzShowInkInFixed"
[nzOffsetTop]="nzOffsetTop"
[nzTargetOffset]="nzTargetOffset"
[nzContainer]="nzContainer"
[nzCurrentAnchor]="nzCurrentAnchor"
(nzClick)="_click($event)"
(nzScroll)="_scroll($event)"
(nzChange)="_change($event)"
>
<nz-link nzHref="#何时使用" nzTitle="何时使用"></nz-link>
<nz-link nzHref="#basic" nzTitle="Basic demo"></nz-link>
Expand Down Expand Up @@ -288,8 +328,11 @@ export class TestComponent {
nzAffix = true;
nzBounds = 5;
nzOffsetTop = 0;
nzTargetOffset?: number;
nzShowInkInFixed = false;
nzContainer: any = null;
nzCurrentAnchor?: string;
_click() {}
_change() {}
_scroll() {}
}
14 changes: 14 additions & 0 deletions components/anchor/demo/customize-highlight.md
@@ -0,0 +1,14 @@
---
order: 4
title:
zh-CN: 自定义锚点高亮
en-US: Customize the anchor highlight
---

## zh-CN

自定义锚点高亮。

## en-US

Customize the anchor highlight.
16 changes: 16 additions & 0 deletions components/anchor/demo/customize-highlight.ts
@@ -0,0 +1,16 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-anchor-customize-highlight',
template: `
<nz-anchor nzCurrentAnchor="#components-anchor-demo-static">
<nz-link nzHref="#components-anchor-demo-basic" nzTitle="Basic demo"></nz-link>
<nz-link nzHref="#components-anchor-demo-static" nzTitle="Static demo"></nz-link>
<nz-link nzHref="#api" nzTitle="API">
<nz-link nzHref="#nz-anchor" nzTitle="nz-anchor"></nz-link>
<nz-link nzHref="#nz-link" nzTitle="nz-link"></nz-link>
</nz-link>
</nz-anchor>
`
})
export class NzDemoAnchorCustomizeHighlightComponent {}
14 changes: 14 additions & 0 deletions components/anchor/demo/on-change.md
@@ -0,0 +1,14 @@
---
order: 6
title:
zh-CN: 监听锚点链接改变
en-US: Listening for anchor link change
---

## zh-CN

监听锚点链接改变

## en-US

Listening for anchor link change.
20 changes: 20 additions & 0 deletions components/anchor/demo/on-change.ts
@@ -0,0 +1,20 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-anchor-on-change',
template: `
<nz-anchor (nzChange)="handleChange($event)">
<nz-link nzHref="#components-anchor-demo-basic" nzTitle="Basic demo"></nz-link>
<nz-link nzHref="#components-anchor-demo-static" nzTitle="Static demo"></nz-link>
<nz-link nzHref="#api" nzTitle="API">
<nz-link nzHref="#nz-anchor" nzTitle="nz-anchor"></nz-link>
<nz-link nzHref="#nz-link" nzTitle="nz-link"></nz-link>
</nz-link>
</nz-anchor>
`
})
export class NzDemoAnchorOnChangeComponent {
handleChange(link: string): void {
console.log('Anchor:OnChange', link);
}
}
14 changes: 14 additions & 0 deletions components/anchor/demo/on-click.md
@@ -0,0 +1,14 @@
---
order: 3
title:
zh-CN: 自定义 onClick 事件
en-US: Customize the onClick event
---

## zh-CN

点击锚点不记录历史。

## en-US

Clicking on an anchor does not record history.
20 changes: 20 additions & 0 deletions components/anchor/demo/on-click.ts
@@ -0,0 +1,20 @@
import { Component } from '@angular/core';

@Component({
selector: 'nz-demo-anchor-on-click',
template: `
<nz-anchor (nzClick)="handleClick($event)">
<nz-link nzHref="#components-anchor-demo-basic" nzTitle="Basic demo"></nz-link>
<nz-link nzHref="#components-anchor-demo-static" nzTitle="Static demo"></nz-link>
<nz-link nzHref="#api" nzTitle="API">
<nz-link nzHref="#nz-anchor" nzTitle="nz-anchor"></nz-link>
<nz-link nzHref="#nz-link" nzTitle="nz-link"></nz-link>
</nz-link>
</nz-anchor>
`
})
export class NzDemoAnchorOnClickComponent {
handleClick(e: string): void {
console.log(e);
}
}
14 changes: 14 additions & 0 deletions components/anchor/demo/target-offset.md
@@ -0,0 +1,14 @@
---
order: 5
title:
zh-CN: 设置锚点滚动偏移量
en-US: Set Anchor scroll offset
---

## zh-CN

锚点目标滚动到屏幕正中间。

## en-US

Anchor target scroll to screen center.
22 changes: 22 additions & 0 deletions components/anchor/demo/target-offset.ts
@@ -0,0 +1,22 @@
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'nz-demo-anchor-target-offset',
template: `
<nz-anchor [nzTargetOffset]="targetOffset">
<nz-link nzHref="#components-anchor-demo-basic" nzTitle="Basic demo"></nz-link>
<nz-link nzHref="#components-anchor-demo-static" nzTitle="Static demo"></nz-link>
<nz-link nzHref="#api" nzTitle="API">
<nz-link nzHref="#nz-anchor" nzTitle="nz-anchor"></nz-link>
<nz-link nzHref="#nz-link" nzTitle="nz-link"></nz-link>
</nz-link>
</nz-anchor>
`
})
export class NzDemoAnchorTargetOffsetComponent implements OnInit {
targetOffset?: number;

ngOnInit(): void {
this.targetOffset = window.innerHeight / 2;
}
}
4 changes: 4 additions & 0 deletions components/anchor/doc/index.en-US.md
Expand Up @@ -25,13 +25,17 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor';
| `[nzBounds]` | Bounding distance of anchor area, unit: px | `number` | `5` ||
| `[nzOffsetTop]` | Pixels to offset from top when calculating position of scroll | `number` | `0` ||
| `[nzShowInkInFixed]` | Whether show ink-balls in Fixed mode | `boolean` | `false` ||
| `[nzTargetOffset]` | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | |
| `[nzContainer]` | Scrolling container | `string \| HTMLElement` | `window` |
| `[nzCurrentAnchor]` | Customize the anchor highlight | string | - | |
| `(nzClick)` | Click of Anchor item | `EventEmitter<string>` | - |
| `(nzChange)` | Listening for anchor link change | `EventEmitter<string>` | - | |
| `(nzScroll)` | The scroll function that is triggered when scrolling to an anchor. | `EventEmitter<NzAnchorLinkComponent>` | - |

### nz-link

| Property | Description | Type | Default |
| -------- | ----------- | ---- | ------- |
| `[nzHref]` | target of hyperlink | `string` | - |
| `[nzTarget]` | Specifies where to display the linked URL | string | - | |
| `[nzTitle]` | content of hyperlink | `string \| TemplateRef<void>` | - |
4 changes: 4 additions & 0 deletions components/anchor/doc/index.zh-CN.md
Expand Up @@ -27,13 +27,17 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor';
| `[nzBounds]` | 锚点区域边界,单位:px | `number` | `5` ||
| `[nzOffsetTop]` | 距离窗口顶部达到指定偏移量后触发 | `number` | - ||
| `[nzShowInkInFixed]` | 固定模式是否显示小圆点 | `boolean` | `false` ||
| `[nzTargetOffset]` | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | |
| `[nzContainer]` | 指定滚动的容器 | `string \| HTMLElement` | `window` |
| `[nzCurrentAnchor]` | 自定义高亮的锚点 | string | - | |
| `(nzClick)` | 点击项触发 | `EventEmitter<string>` | - |
| `(nzChange)` | 监听锚点链接改变 | `EventEmitter<string>` | - | |
| `(nzScroll)` | 滚动至某锚点时触发 | `EventEmitter<NzAnchorLinkComponent>` | - |

### nz-link

| 成员 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `[nzHref]` | 锚点链接 | `string` | - |
| `[nzTarget]` | 该属性指定在何处显示链接的资源。 | string | - | |
| `[nzTitle]` | 文字内容 | `string \| TemplateRef<void>` | - |

0 comments on commit 254b429

Please sign in to comment.