Skip to content

Commit

Permalink
feat(logic): use Renderer2
Browse files Browse the repository at this point in the history
  • Loading branch information
rbalet committed Nov 27, 2024
1 parent 4b66bf6 commit b0627a5
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 67 deletions.
50 changes: 12 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ A library that allows href to understand Angular's router while retaining its de
2. Support scroll with the `#` attributes and let you configure the [scrolling logic](#scroll-logic)
3. Automatically append `rel="nooepener"` & `target="_blank"` to external link [if wished so](#installation)
4. Support using `href` with the html `button` [attribute](#directive)
5. Enable easy `Scroll when ready` mechanism
5. Enable easy `Scroll when ready` mechanism which works with `SSR`
6. Let you transform text to well formatted `anchor`

## Demo
- https://stackblitz.com/~/github.com/rbalet/ngx-href

## 19.0.0 Breaking change
* **Now use `scrollIntoView` which render the `Offset` useless.**
* Please use [scroll-margin-top](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top) instead.
* Nows also work on SSR

## Installation

```sh
Expand All @@ -31,8 +36,8 @@ import { NgxHrefModule } from 'ngx-href'
/** Default
* avoidSpam="false"
* behavior="auto"
* defaultOffset="0"
* navbarOffset="0"
* block="start"
* inline="nearest"
* rel=undefined
* retryTimeout=undefined
* target="_self"
Expand All @@ -43,8 +48,8 @@ import { NgxHrefModule } from 'ngx-href'
NgxHrefModule.forRoot({
avoidSpam: true,
behavior:"smooth",
defaultOffset:"30",
navbarOffset:"60",
block:"center",
inline:"nearest",
rel:"noopener nofollow",
retryTimeout: 300,
target:"_blank",
Expand All @@ -69,39 +74,8 @@ Can also be passed individually directly through html
<a href="https://my-external-url.com" behavior="instant">
```

### defaultOffset
The standard offset to be added to your website `scrollTo` logic

**Default:** `0`
**Accepted value:** `number`
Together with the `navbarOffset` will be the total offset for the scroll.

### navbarOffset
An additional offset calculated base on your navbar height

**Default:** `0`
**Accepted value:** `number`
Together with the `defaultOffset` will be the total offset for the scroll.

You can update this value after the navbar is rendered.

```html
<navbar #navbar>
<!-- My html code -->
</navbar>
```

```typescript
@ViewChild('navbar', { static: true }) navbar: ElementRef

constructor(
private _ngxHrefService: NgxHrefService,
) {}

ngAfterContentInit(): void {
this._ngxHrefService.navbarOffset = this.navbar.nativeElement.offsetHeight
}
```
### Offset
If you wish to add offset, add `scroll-margin-top: $offset` to your targeted component -> [read more](https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-margin-top)

### retryTimeout
**Default:** `undefined`
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-href",
"version": "18.2.0",
"version": "19.0.0",
"license": "MIT",
"author": "Raphael Balet",
"maintainers": [
Expand Down
2 changes: 1 addition & 1 deletion projects/ngx-href/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ngx-href",
"version": "18.1.2",
"version": "19.0.0",
"license": "MIT",
"author": {
"name": "Raphaël Balet",
Expand Down
4 changes: 2 additions & 2 deletions projects/ngx-href/src/lib/href.interface.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export interface NgxHrefServiceConfig {
avoidSpam?: boolean
behavior?: ScrollBehavior
navbarOffset?: number
defaultOffset?: number
block?: ScrollLogicalPosition
defaultRelAttr?: string
defaultTargetAttr?: string
inline?: ScrollLogicalPosition
retryTimeout?: number
}
45 changes: 20 additions & 25 deletions projects/ngx-href/src/lib/href.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Inject, Injectable } from '@angular/core'
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'
import { BehaviorSubject } from 'rxjs'
import { NgxHrefServiceProvider } from './href.const'
import { NgxHrefServiceConfig } from './href.interface'
Expand All @@ -7,27 +7,34 @@ import { NgxHrefServiceConfig } from './href.interface'
providedIn: 'root',
})
export class NgxHrefService {
private renderer: Renderer2

anchor$: BehaviorSubject<string | null> = new BehaviorSubject<string | null>(null)
loadedAnchor$: BehaviorSubject<string | null> = new BehaviorSubject<string | null>(null) // Trigger the scrollTo mechanism from outside

avoidSpam?: boolean
behavior!: ScrollBehavior
defaultOffset!: number
navbarOffset!: number
block!: ScrollLogicalPosition
defaultRelAttr?: string
defaultTargetAttr!: string
inline!: ScrollLogicalPosition
retryTimeout?: number

private _actualAnchor?: string

constructor(@Inject(NgxHrefServiceProvider) _config: NgxHrefServiceConfig) {
constructor(
@Inject(NgxHrefServiceProvider) _config: NgxHrefServiceConfig,
_rendererFactory: RendererFactory2,
) {
this.renderer = _rendererFactory.createRenderer(null, null)

this.avoidSpam = _config.avoidSpam
this.behavior = _config.behavior || 'auto'
this.defaultOffset = typeof _config.defaultOffset === 'number' ? _config.defaultOffset : 0
this.navbarOffset = typeof _config.navbarOffset === 'number' ? _config.navbarOffset : 0
this.block = _config.block || 'start'
this.defaultRelAttr = _config.defaultRelAttr
this.defaultTargetAttr = _config.defaultTargetAttr || '_self'
this.retryTimeout = _config.retryTimeout
this.inline = _config.inline || 'nearest'
this.retryTimeout = _config.retryTimeout || 0

this.loadedAnchor$.subscribe((anchor) => {
if (anchor === this._actualAnchor) {
Expand Down Expand Up @@ -55,28 +62,16 @@ export class NgxHrefService {
this.setAnchor(anchor)
}

const anchorRef = document.getElementById(anchor)
const anchorRef: HTMLElement = this.renderer.selectRootElement(`#${anchor}`, true)

if (anchorRef) {
const offsetPosition =
anchorRef.getBoundingClientRect().top +
window.scrollY -
(this.navbarOffset + this.defaultOffset)

window.scrollTo({
top: offsetPosition,
behavior: this.behavior,
})
anchorRef.scrollIntoView({ behavior: this.behavior, block: this.block, inline: this.inline })

if (this.retryTimeout)
setTimeout(() => {
window.scrollTo({
top: offsetPosition,
behavior: this.behavior,
})
}, this.retryTimeout)
setTimeout(() => {
anchorRef.scrollIntoView({ behavior: this.behavior })

this._actualAnchor = undefined
this._actualAnchor = undefined
}, this.retryTimeout)
} else {
setTimeout(() => {
if (anchor !== this._actualAnchor) return
Expand Down

0 comments on commit b0627a5

Please sign in to comment.