Last active
August 8, 2017 12:27
-
-
Save ChrisMBarr/a355b3c8c212656a65778d42f37c5b06 to your computer and use it in GitHub Desktop.
Angular2 Sticky Element Directive
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="row"> | |
<div class="col-md-8"> | |
<p>This is some content</p> | |
</div> | |
<div class="col-md-4"> | |
<aside appSticky [offset]="20"> | |
This is the sidebar | |
</aside> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, ElementRef, Input, HostListener, OnDestroy } from '@angular/core'; | |
@Directive({ | |
selector: '[appSticky]' | |
}) | |
export class StickyDirective implements OnDestroy { | |
@Input() offset = 0; | |
@Input() stickyClass = 'sticky'; | |
@Input() stickyMinWidth = 992; //default to only be sticky at the Bootstrap MD sized screen and higher | |
private canStick = false; | |
private $element: JQuery; | |
private originalStyles: string | null; | |
private $parentElement: JQuery; | |
private originalParentPosition: string; | |
constructor(private element: ElementRef) { | |
this.$element = $(this.element.nativeElement); | |
this.originalStyles = this.element.nativeElement.style; | |
this.$parentElement = this.$element.parent(); | |
this.originalParentPosition = this.$parentElement.css('position'); | |
this.$parentElement.css('position', 'relative'); | |
this.handleResizeEvent(); | |
} | |
private determineStickiness() { | |
if (this.canStick) { | |
const elOffset = this.$parentElement.offset(); | |
const elTop = elOffset ? elOffset.top - this.offset : this.offset; | |
if (window.pageYOffset > elTop) { | |
this.element.nativeElement.classList.add(this.stickyClass); | |
this.setStyles(); | |
} else { | |
this.element.nativeElement.classList.remove(this.stickyClass); | |
this.removeStyles(); | |
} | |
} else { | |
this.removeStyles(); | |
} | |
} | |
private setStyles() { | |
const parentWidth = this.$parentElement.width(); | |
this.$element.css({ | |
position: 'fixed', | |
top: this.offset, | |
width: typeof parentWidth === 'number' ? parentWidth : 'auto' | |
}); | |
} | |
private removeStyles() { | |
this.$element.css({ | |
position: '', | |
top: 'auto', | |
width: 'auto' | |
}); | |
} | |
@HostListener('window:scroll') | |
handleScrollEvent() { | |
this.determineStickiness(); | |
} | |
@HostListener('window:resize') | |
handleResizeEvent() { | |
this.canStick = window.innerWidth > this.stickyMinWidth; | |
this.determineStickiness(); | |
} | |
ngOnDestroy() { | |
this.$parentElement.css('position', this.originalParentPosition); | |
this.element.nativeElement.style = this.originalStyles; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment