Skip to content

Commit

Permalink
feat: Adding directives and pipes 🚧
Browse files Browse the repository at this point in the history
  • Loading branch information
flauc committed Jun 16, 2018
1 parent 65e68e5 commit b410aeb
Show file tree
Hide file tree
Showing 7 changed files with 227 additions and 28 deletions.
8 changes: 4 additions & 4 deletions projects/ng-helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "ng-helpers",
"name": "@jaspero/ng-helpers",
"version": "0.0.1",
"peerDependencies": {
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"
"@angular/common": "^6.0.0",
"@angular/core": "^6.0.0"
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
import { Directive } from '@angular/core';
import {
AfterViewInit,
Directive,
ElementRef,
EventEmitter,
Input,
NgZone,
Output
} from '@angular/core';
import {fromEvent} from 'rxjs';
import {filter, takeUntil} from 'rxjs/operators';
import {RxDestroy} from '../../helpers/rx-destroy';

/**
* Emits an event when a click action occurs that does not target the element
*
* @example
* <div (jpClickOutside)="doSomething()"></div>
*/
@Directive({
selector: '[libClickOutside]'
selector: '[jpClickOutside]'
})
export class ClickOutsideDirective {
export class ClickOutsideDirective extends RxDestroy implements AfterViewInit {
constructor(private _el: ElementRef, private _ngZone: NgZone) {
super();
}

constructor() { }
/**
* Any valid html event
* @type {string}
*/
@Input() clickOutsideEventType = 'click';

/**
* if true jpClickOutside doesn't emit
* @type {boolean}
*/
@Input() clickOutsideBlock = false;

/**
* Emits when triggered event doesn't contain this e
* @type {EventEmitter<MouseEvent>}
*/
@Output() jpClickOutside = new EventEmitter<MouseEvent>();

ngAfterViewInit() {
this._ngZone.runOutsideAngular(() => {
fromEvent<MouseEvent>(window, this.clickOutsideEventType)
.pipe(
takeUntil(this.destroyed$),
filter(
event =>
!this.clickOutsideBlock &&
!this._el.nativeElement.contains(event.target)
)
)
.subscribe(event => {
this._ngZone.run(() => {
this.jpClickOutside.emit(event);
});
});
});
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,45 @@
import { Directive } from '@angular/core';
import {Directive, EventEmitter, HostListener, Input, Output} from '@angular/core';
import {FormGroup} from '@angular/forms';

@Directive({
selector: '[libFormTouchOnHover]'
selector: '[jpFormTouchOnHover]'
})
export class FormTouchOnHoverDirective {
export class TouchFormOnHoverDirective {

constructor() { }
/**
* Entry FormGroup which to iterate over
*/
@Input() jpFormTouchOnHover: FormGroup;

/**
* Outputs when form finish iterating
* @type {EventEmitter<any>}
*/
@Output() jpFormTouched = new EventEmitter();

@HostListener('mouseenter')
enter() {
this._markFormGroupTouched(this.jpFormTouchOnHover);
}

private _markFormGroupTouched(formGroup: FormGroup) {
(Object.values(formGroup.controls) as any[])
.forEach(control => {
control.markAsTouched();

if (control && control.controls) {
if (Array.isArray(control.controls)) {
control.controls.forEach(c => this._markFormGroupTouched(c));
} else {
for (const key in control.controls) {
if (control.controls.hasOwnProperty(key)) {
control.controls[key].markAsTouched();
}
}
}
}
});

this.jpFormTouched.emit(1);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
import { Directive } from '@angular/core';
import {
Directive,
Output,
EventEmitter,
Renderer2,
ElementRef,
OnDestroy,
OnInit,
Input
} from '@angular/core';

/**
* Used for preventing propagation on event calls event.stopPropagation())
*
* @example
* <div (jpStopPropagation)="doSomething()"></div>
*/
@Directive({
selector: '[libStopPropagation]'
selector: '[jpStopPropagation]'
})
export class StopPropagationDirective {
export class StopPropagationDirective implements OnInit, OnDestroy {
constructor(private _renderer: Renderer2, private _el: ElementRef) {}

constructor() { }
/**
* Any valid html event
* @type {string}
*/
@Input() stopPropagationEventType = 'click';

/**
* Should preventDefault also be called
* @type {boolean}
*/
@Input() preventDefault = false;

/**
* Outputs the input event
* @type {EventEmitter<any>}
*/
@Output() jpStopPropagation = new EventEmitter();

private _eventListener: any;

ngOnInit() {
this._eventListener = this._renderer.listen(
this._el.nativeElement,
this.stopPropagationEventType,
event => {
if (this.preventDefault) {
event.preventDefault();
}

event.stopPropagation();
this.jpStopPropagation.emit(event);
}
);
}

ngOnDestroy() {
try {
this._eventListener.unsubscribe();
} catch (e) {}
}
}
25 changes: 20 additions & 5 deletions projects/ng-helpers/src/pipes/enum/enum.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { Pipe, PipeTransform } from '@angular/core';
import {Pipe, PipeTransform} from '@angular/core';

/**
* Returns an array of {key: number, value: string} objects.
* Most useful in *ngFor iterations
*
* @example
* <div *ngFor="let item of someEnum | enum></div>
*
*/
@Pipe({
name: 'enum'
})
export class EnumPipe implements PipeTransform {

transform(value: any, args?: any): any {
return null;
public transform(value): Array<{key: number; value: string}> {
const keys = [];
for (const enumMember in value) {
if (value[enumMember]) {
const val = parseInt(enumMember, 10);
if (!isNaN(val)) {
keys.push({key: val, value: value[enumMember]});
}
}
}
return keys;
}

}
27 changes: 23 additions & 4 deletions projects/ng-helpers/src/pipes/sanitize/sanitize.pipe.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import { Pipe, PipeTransform } from '@angular/core';
import {Pipe, PipeTransform} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';

/**
* Applies the appropriate DomSanitizer method
* to inputted value.
*
* @example
* <div [innerHtml]="someHtmlValue | sanitize"></div>
*/
@Pipe({
name: 'sanitize'
})
export class SanitizePipe implements PipeTransform {
constructor(
private _sanitizer: DomSanitizer
) {}

transform(value: any, args?: any): any {
return null;
}
transform(value: string, type = 'html') {

const sanitizeMap = {
html: 'bypassSecurityTrustHtml',
style: 'bypassSecurityTrustStyle',
script: 'bypassSecurityTrustScript',
url: 'bypassSecurityTrustUrl',
resourceUrl: 'bypassSecurityTrustResourceUrl'
};

return this._sanitizer[sanitizeMap[type]](value);
}
}
28 changes: 25 additions & 3 deletions projects/ng-helpers/src/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@
* Public API Surface of ng-helpers
*/

export * from './lib/ng-helpers.service';
export * from './lib/ng-helpers.component';
export * from './lib/ng-helpers.module';
/**
* Helpers
*/
export * from './helpers/rx-destroy';

/**
* Directives
*/
export * from './directives/click-outside/click-outside.module';
export * from './directives/click-outside/click-outside.directive';

export * from './directives/stop-propagation/stop-propagation.module';
export * from './directives/stop-propagation/stop-propagation.directive';

export * from './directives/form-touch-on-hover/form-touch-on-hover.module';
export * from './directives/form-touch-on-hover/form-touch-on-hover.directive';

/**
* Pipes
*/
export * from './pipes/enum/enum.module';
export * from './pipes/enum/enum.pipe';

export * from './pipes/sanitize/sanitize.module';
export * from './pipes/sanitize/sanitize.pipe';

0 comments on commit b410aeb

Please sign in to comment.