Skip to content

Instantly share code, notes, and snippets.

@euangoddard
Last active September 20, 2018 13:56
Show Gist options
  • Save euangoddard/52b3d54061ce0ec41e0f66385fd3ad45 to your computer and use it in GitHub Desktop.
Save euangoddard/52b3d54061ce0ec41e0f66385fd3ad45 to your computer and use it in GitHub Desktop.
Alias directive for Angular
import { Component } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AliasDirective } from './alias.directive';
describe('Alias directive', () => {
beforeEach(() =>
TestBed.configureTestingModule({
declarations: [AliasDirective, DoubleComponent, TripleComponent],
}));
it('should respond to changes in the host', () => {
const fixture = TestBed.createComponent(DoubleComponent);
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('h1')).nativeElement.textContent).toEqual('4');
fixture.componentInstance.value = 10;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('h1')).nativeElement.textContent).toEqual('20');
});
it('should support the "as" notation', () => {
const fixture = TestBed.createComponent(TripleComponent);
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('h1')).nativeElement.textContent).toEqual('6');
});
});
@Component({
template: `<h1 *alias="double(value); let doubled">{{ doubled }}</h1>`,
})
class DoubleComponent {
value = 2;
double(value: number): number {
return value * 2;
}
}
@Component({
template: `<h1 *alias="triple(value) as tripled">{{ tripled }}</h1>`,
})
class TripleComponent {
value = 2;
triple(value: number): number {
return value * 3;
}
}
import { Directive, EmbeddedViewRef, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[alias]',
})
export class AliasDirective {
private context: AliasContext = { $implicit: null, alias: null };
private viewRef: EmbeddedViewRef<AliasContext> = null;
constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef<AliasContext>) {}
@Input()
set alias(source: any) {
this.context.$implicit = this.context.alias = source;
if (!this.viewRef) {
this.viewContainer.clear();
this.viewRef = this.viewContainer.createEmbeddedView(this.templateRef, this.context);
} else {
this.viewRef.markForCheck();
}
}
}
interface AliasContext {
$implicit: any;
alias: any;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment