EL-Lib is a library of common Angular components, directives, pipes and so on that I use in my Electron projects. I don't expect anyone else will ever use this library as-is but you may find some of its ideas and techniques useful.
Just in case ...
npm install --save ellib
import { LibModule } from 'ellib';
@NgModule({
imports: [LibModule]
})
Just use in place of <router-outlet>
for a slide-in effect on route transitions.
<lib-animated-router-outlet>
</lib-animated-router-outlet>
Wrap content so that drawers of related content slide out on command from the top, right, bottom and/or left. The drawers are modal. Examples might be filters, preferences, CRUD support and the like.
<lib-drawer-container>
<my-toolbar
(showPrefs)="prefsDrawer.open()">
</my-toolbar>
...
<lib-drawer-panel
#prefsDrawer
position="right">
...
</lib-drawer-panel>
</lib-drawer-container>
Wrap arbitrary markdown, which will be converted to HTML as the component loads.
<lib-markdown>
# Hello, World!
</lib-markdown>
Requires marked
which might be loaded via .angular-cli.json
.
"scripts": [
"../node_modules/marked/marked.min.js"
],
Annotates a components so that any RxJS subscriptions are automatically unsubscribed when the component is destroyed.
import { AutoUnsubscribe } from 'ellib';
import { LifecycleComponent } from 'ellib';
@Component({...})
@AutoUnsubscribe()
export class MyComponent extends LifecycleComponent {
private mySubscription: Subscription;
private anotherSubscription: Subscription;
constructor(...) {
super();
// sadly if you have a ctor you have to remember to call super!
}
// if non null when the component is destroyed, both will be unsubscribed
// automatically -- no other action needed
}
Greatly simplifies ngOnChanges
handling for @Input()
fields, and is especially useful when those fields are supplied via the async
pipe and you need to know when they've changed.
import { OnChange } from 'ellib';
import { LifecycleComponent } from 'ellib';
@Component({...})
export class MyComponent extends LifecycleComponent {
@Input() a;
@Input() b;
constructor(...) {
super();
// sadly if you have a ctor you have to remember to call super!
}
@OnChange('a', 'b')
myChanges(changedA: boolean, changedB: boolean) {
// the name of this method is arbitrary
// if multiple fields are coded, then it is called if EITHER changes
// a boolean is passed for each so you can tell what changed
if (this.a && this.changedA) { ... }
}
}
It took me ages to get these right. Maybe I'm not so smart as I think! I do know that I hate DSLs. I think they're all a fraud. They pretend to be intuitive but there's no way to discern the API without examples, so I offer mine as models to use, discard or improve on.
Animates the changing contents of a container by fading in the new and fading out the old.
import { inOutAnimation } from 'ellib';
@Component({
animations: [inOutAnimation()],
...
})
<div [@inOut]="... expression that identifies contents ...">
...
</div>
Shows the contents of a container by expanding it height to fit; hides the contents by shrinking its height to zero.
import { showHideAnimation } from 'ellib';
@Component({
animations: [showHideAnimation()],
...
})
<div [@showHide]="expertMode? 'shown' : 'hidden'">
...
</div>
Designed to be used by the AnimatedRouterOutletComponent
as described above. It slides the contents of the old route out to the right, and the new in from the left.
export declare function debounce(func: Function, wait?: number, immediate?: boolean): Function;
export declare function deepCopy<T>(obj: T): T;
export declare function dump(data: Uint8Array, title: string, ebcdic?: boolean, color?: string): void;
export declare function isObjectEmpty(obj: any): boolean;
export declare function nextTick(f: Function): void;
export declare function reverseMap(obj: any): any;
export declare function toHex(num: number, pad: number): string;
Very useful when you want to debounce but using Observable
is impossible or inconvenient.
import { debounce } from 'ellib';
setup: Function;
this.setup = debounce((...) => {
...
}, 250);
Produces a nice, expandable dump of large objects (like Buffers) to the console.
A semantic recasting of setTimeout(..., 0)
when used (for example) In Angular to force rendering.
import { nextTick } from 'ellib';
nextTick((...) => {
...
});