Skip to content

Instantly share code, notes, and snippets.

@ChrisMBarr
Last active August 8, 2017 12:27
Show Gist options
  • Save ChrisMBarr/a355b3c8c212656a65778d42f37c5b06 to your computer and use it in GitHub Desktop.
Save ChrisMBarr/a355b3c8c212656a65778d42f37c5b06 to your computer and use it in GitHub Desktop.
Angular2 Sticky Element Directive
<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>
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