-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added angular integration library 'ng-aux-library'
- Loading branch information
Showing
9 changed files
with
372 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
See `doc/docs/Angular.md` for information about how to use these directives. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { Directive, ElementRef, Inject, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike, isObservable } from 'rxjs'; | ||
import { AuxSubscriptions } from './aux-subscriptions.model'; | ||
|
||
@Directive({ | ||
selector: '[auxAssign]' | ||
}) | ||
export class AuxAssignDirective extends AuxSubscriptions | ||
{ | ||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
if (isObservable(b)) | ||
{ | ||
const o = b as Observable<any>; | ||
return o.subscribe((v) => { | ||
widget.set(name, v); | ||
}); | ||
} | ||
else | ||
{ | ||
widget.set(name, b); | ||
|
||
// nothing was subscribed | ||
return null; | ||
} | ||
} | ||
|
||
@Input('auxAssign') | ||
set auxAssign(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { Directive, ElementRef, Inject, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike, isObservable } from 'rxjs'; | ||
import { AuxSubscriptions } from './aux-subscriptions.model'; | ||
import { DebounceBinding } from '@deuso/aux'; | ||
|
||
@Directive({ | ||
selector: '[auxBind]' | ||
}) | ||
export class AuxBindDirective extends AuxSubscriptions | ||
{ | ||
private bindings = new Map<string,DebounceBinding>(); | ||
|
||
protected remove_binding(widget: any, name: string) | ||
{ | ||
let binding = this.bindings.get(name); | ||
|
||
if (binding) | ||
{ | ||
this.bindings.delete(name); | ||
binding.destroy(); | ||
} | ||
} | ||
|
||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
let binding = this.bindings.get(name); | ||
|
||
if (!binding) | ||
{ | ||
this.bindings.set(name, binding = new DebounceBinding(widget, name, 250)); | ||
} | ||
|
||
if (isObservable(b)) | ||
{ | ||
const o = b as Observable<any>; | ||
return o.subscribe((v) => { | ||
binding.set(v); | ||
}); | ||
} | ||
else | ||
{ | ||
binding.set(b); | ||
|
||
// nothing was subscribed | ||
return null; | ||
} | ||
} | ||
|
||
@Input('auxBind') | ||
set auxBind(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { NgModule } from '@angular/core'; | ||
import { AuxAssignDirective } from './aux-assign.directive'; | ||
import { AuxBindDirective } from './aux-bind.directive'; | ||
import { AuxInterceptDirective } from './aux-intercept.directive'; | ||
import { AuxObserveAllDirective } from './aux-observe-all.directive'; | ||
import { AuxObserveDirective } from './aux-observe.directive'; | ||
import { AuxSubscribeDirective } from './aux-subscribe.directive'; | ||
|
||
|
||
@NgModule({ | ||
declarations: [ | ||
AuxAssignDirective, | ||
AuxBindDirective, | ||
AuxInterceptDirective, | ||
AuxObserveAllDirective, | ||
AuxObserveDirective, | ||
AuxSubscribeDirective | ||
], | ||
exports: [ | ||
AuxAssignDirective, | ||
AuxBindDirective, | ||
AuxInterceptDirective, | ||
AuxObserveAllDirective, | ||
AuxObserveDirective, | ||
AuxSubscribeDirective | ||
], | ||
imports: [ ] | ||
}) | ||
export class AuxDirectivesModule { } |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Directive, ElementRef, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike } from 'rxjs'; | ||
import { | ||
AuxSubscriptions, make_subscription | ||
} from './aux-subscriptions.model'; | ||
import { intercept_option } from '@deuso/aux'; | ||
|
||
@Directive({ | ||
selector: '[auxIntercept]' | ||
}) | ||
export class AuxInterceptDirective extends AuxSubscriptions | ||
{ | ||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
if (typeof(b) === 'object' && b.next) | ||
{ | ||
return make_subscription(intercept_option(widget, name, (v) => { | ||
b.next(v); | ||
})); | ||
} | ||
else if (typeof(b) === 'function') | ||
{ | ||
return make_subscription(intercept_option(widget, name, b)); | ||
} | ||
else | ||
{ | ||
throw new Error("Unsupported binding type."); | ||
} | ||
} | ||
|
||
@Input('auxIntercept') | ||
set auxIntercept(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Directive, ElementRef, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike } from 'rxjs'; | ||
import { | ||
AuxSubscriptions, make_subscription | ||
} from './aux-subscriptions.model'; | ||
import { observe_option } from '@deuso/aux'; | ||
|
||
@Directive({ | ||
selector: '[auxObserveAll]' | ||
}) | ||
export class AuxObserveAllDirective extends AuxSubscriptions { | ||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
if (typeof(b) === 'object' && b.next) | ||
{ | ||
return make_subscription(observe_option(widget, name, (v) => { | ||
b.next(v); | ||
})); | ||
} | ||
else if (typeof(b) === 'function') | ||
{ | ||
return make_subscription(observe_option(widget, name, b)); | ||
} | ||
else | ||
{ | ||
throw new Error("Unsupported binding type."); | ||
} | ||
} | ||
|
||
@Input('auxObserveAll') | ||
set auxObserveAll(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Directive, ElementRef, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike } from 'rxjs'; | ||
import { | ||
AuxSubscriptions, make_subscription | ||
} from './aux-subscriptions.model'; | ||
import { observe_useraction } from '@deuso/aux'; | ||
|
||
@Directive({ | ||
selector: '[auxObserve]' | ||
}) | ||
export class AuxObserveDirective extends AuxSubscriptions { | ||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
if (typeof(b) === 'object' && b.next) | ||
{ | ||
return make_subscription(observe_useraction(widget, name, (v) => { | ||
b.next(v); | ||
})); | ||
} | ||
else if (typeof(b) === 'function') | ||
{ | ||
return make_subscription(observe_useraction(widget, name, b)); | ||
} | ||
else | ||
{ | ||
throw new Error("Unsupported binding type."); | ||
} | ||
} | ||
|
||
@Input('auxObserve') | ||
set auxObserve(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Directive, ElementRef, Input } from '@angular/core'; | ||
import { Observable, SubscriptionLike } from 'rxjs'; | ||
import { | ||
AuxSubscriptions, aux_subscribe | ||
} from './aux-subscriptions.model'; | ||
|
||
@Directive({ | ||
selector: '[auxSubscribe]' | ||
}) | ||
export class AuxSubscribeDirective extends AuxSubscriptions { | ||
protected install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike | ||
{ | ||
if (typeof(b) === 'object' && b.next) | ||
{ | ||
return aux_subscribe(widget, name, (...args) => { | ||
b.next(args); | ||
}); | ||
} | ||
else if (typeof(b) === 'function') | ||
{ | ||
return aux_subscribe(widget, name, b); | ||
} | ||
else | ||
{ | ||
throw new Error("Unsupported binding type."); | ||
} | ||
} | ||
|
||
@Input('auxSubscribe') | ||
set auxSubscribe(bindings: {[name: string]: any}|null) | ||
{ | ||
this.update(bindings); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { ElementRef, Inject, OnDestroy } from '@angular/core'; | ||
import { SubscriptionLike } from 'rxjs'; | ||
|
||
export function make_subscription(subscription: Function): SubscriptionLike | ||
{ | ||
return { | ||
closed: false, | ||
unsubscribe() | ||
{ | ||
if (this.closed) return; | ||
this.closed = true; | ||
subscription(); | ||
}, | ||
}; | ||
} | ||
|
||
export function aux_subscribe(widget: any, name: string, | ||
_cb: any): SubscriptionLike | ||
{ | ||
return make_subscription(widget.subscribe(name, (...args) => _cb(...args))); | ||
} | ||
|
||
export abstract class AuxSubscriptions implements OnDestroy | ||
{ | ||
private last: {[name: string]: any}|null = null; | ||
private subscriptions = new Map<string,SubscriptionLike>(); | ||
|
||
protected remove_binding(widget: any, name: string): void | ||
{ | ||
} | ||
|
||
protected abstract install_binding(widget: any, name: string, b: any) | ||
: SubscriptionLike; | ||
|
||
protected update(bindings: {[name: string]: any}|null) | ||
{ | ||
const element = this.el.nativeElement; | ||
const widget = element.auxWidget; | ||
|
||
if (!widget) | ||
{ | ||
if (element.tagName.startsWith('AUX-')) | ||
{ | ||
throw new Error("The AUX WebComponent has not been upgraded, yet. "+ | ||
"Are you missing and import?"); | ||
} | ||
throw new Error("The element is not an AUX WebComponent."); | ||
} | ||
|
||
const last = this.last || {}; | ||
const current = bindings || {}; | ||
|
||
for (let name in last) | ||
{ | ||
// handled by loop below | ||
if (name in current) continue; | ||
|
||
// remove old subscriptions | ||
let subscriptions = this.subscriptions.get(name); | ||
|
||
if (subscriptions) | ||
{ | ||
this.subscriptions.delete(name); | ||
subscriptions.unsubscribe(); | ||
} | ||
|
||
this.remove_binding(widget, name); | ||
} | ||
|
||
for (let name in current) | ||
{ | ||
const value = current[name]; | ||
|
||
if (name in last) | ||
{ | ||
const last_value = last[name]; | ||
|
||
if (last_value === value) continue; | ||
|
||
// remove old subscriptions | ||
const subscriptions = this.subscriptions.get(name); | ||
|
||
if (subscriptions) | ||
{ | ||
this.subscriptions.delete(name); | ||
subscriptions.unsubscribe(); | ||
} | ||
} | ||
|
||
const subscription = this.install_binding(widget, name, value); | ||
|
||
if (subscription) | ||
{ | ||
this.subscriptions.set(name, subscription); | ||
} | ||
} | ||
|
||
// we create a copy to make sure that our state is not | ||
// modified | ||
this.last = bindings ? Object.assign({}, bindings) : null; | ||
} | ||
|
||
constructor(@Inject(ElementRef) private el: ElementRef) { } | ||
|
||
public ngOnDestroy() | ||
{ | ||
this.update(null); | ||
} | ||
} |