Created
May 6, 2018 19:45
Experiment: Injecting A Component Reference Into A Pipe Instance In Angular 6.0.0
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
// Import the core angular services. | |
import { Component } from "@angular/core"; | |
// Import the application components and services. | |
import { FnPipeContext } from "./fn.pipe"; | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
@Component({ | |
selector: "my-app", | |
// Here, we can provide special services that are available in the component | |
// injector. In this case, we're telling the FnPipe to use the AppComponent instance | |
// as the context when executing the "fn" function reference. | |
viewProviders: [ | |
{ | |
provide: FnPipeContext, | |
useClass: AppComponent | |
} | |
], | |
styleUrls: [ "./app.component.less" ], | |
template: | |
` | |
<p> | |
<a (click)="message = 'hello world';">Use message one</a>. | |
<br /> | |
<a (click)="message = 'what it be like';">Use message two</a>. | |
</p> | |
<p> | |
Pipe output: <strong>{{ message | fn:formatMessage }}</strong> | |
</p> | |
` | |
}) | |
export class AppComponent { | |
public message: string; | |
// I initialize the app-component. | |
constructor() { | |
this.message = ""; | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I am the function being invoked by the FnPipe. | |
public formatMessage( value: string ) : string { | |
// We can use the "this" reference here because we are providing the AppComponent | |
// as the FnPipeContext token to the local Injector. Its existence will get the | |
// FnPipe to execute the function reference in the current component context. | |
// -- | |
// NOTE: As always, we could have used the Fat-Arrow notation (=>) to bind this | |
// function to the AppComponent instance, which would obviate the need for the | |
// FnPipeContext token. | |
return( `Context[ ${ this.constructor.name } ] => ${ value }` ); | |
} | |
} |
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
// Import the core angular services. | |
import { Optional } from "@angular/core"; | |
import { Pipe } from "@angular/core"; | |
import { PipeTransform } from "@angular/core"; | |
import { Self } from "@angular/core"; | |
// ----------------------------------------------------------------------------------- // | |
// ----------------------------------------------------------------------------------- // | |
// I provide a dependency-injection token for the Fn pipe execution context. | |
export class FnPipeContext { | |
// ... | |
} | |
@Pipe({ | |
name: "fn", | |
pure: true | |
}) | |
export class FnPipe implements PipeTransform { | |
private context: any; | |
// I initialize the fn-pipe. | |
// -- | |
// NOTE: We are injecting an OPTIONAL context for function execution. | |
constructor( @Optional() @Self() context: FnPipeContext ) { | |
this.context = context || null; | |
} | |
// --- | |
// PUBLIC METHODS. | |
// --- | |
// I pass the first and rest arguments to the given function reference. This pipe | |
// is designed to be used in a template to access a component method: | |
// -- | |
// In a template: {{ valueA | fn : componentMethodRef : valueB }} | |
// -- | |
// ... becomes the invocation: context.componentMethodRef( valueA, valueB ). | |
public transform( | |
headArgument: any, | |
fnReference: Function, | |
...tailArguments: any[] | |
) : any { | |
// Due to the way pipes receive arguments, we can have inputs on both sides of | |
// the function reference. As such, let's join the two input sets when invoking | |
// the given Function reference. | |
return( fnReference.apply( this.context, [ headArgument, ...tailArguments ] ) ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment