Reputation: 3317
I have the following custom pipe in my Angular 8 app:
import { Pipe, PipeTransform } from '@angular/core';
import { MyService} from '../_services/my.service';
@Pipe({
name: 'myPipe'
})
export class MyPipe implements PipeTransform {
constructor(private myService: MyService) {}
transform(value: string): any {
return this.myService.loadForID(value);
}
}
I am trying to transform a value dynamically in a component code, by having the string name only: 'myPipe' but i cannot find anyway to inject/load a pipe dynamically for a string. an online post that i found suggests the following code, but even this seem to require a type (MyService) and not a string
constructor(private injector:Injector) {
injector.get(MyService);
}
is there a way to achieve this in Angular?
Upvotes: 2
Views: 2700
Reputation: 2708
In you app.module
you can use a string:
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ],
providers: [
MyPipe,
{ provide: 'myPipe', useClass: MyPipe }
]
})
export class AppModule { }
Then, you can inject it into your component:
import { Component, Injector } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
constructor(private injector:Injector){
var myInterface = injector.get('myPipe');
myInterface.transform('test');
}
}
Here's a stackblitz showing the example
EDIT
If you want to avoid the deprecated call to injector.get
but still be able to access the service from the injector with a string, you can use a service to figure out which injection token should be used. I don't think this is the prettiest way to do it, but I think it meets OPs needs.
First create a Service to map a string to the expected injection token:
@Injectable()
export class TokenService {
static MY_PIPE_TOKEN = new InjectionToken<MyPipe>('myPipe');
getToken(name: string): InjectionToken<any> {
if (name === 'myPipe') {
return TokenService.MY_PIPE_TOKEN;
} else {
throw `No token with name ${name} found`;
}
}
}
Set up your providers, using the Injection Token from the Service:
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, HelloComponent ],
bootstrap: [ AppComponent ],
providers: [
TokenService,
MyPipe,
{ provide: TokenService.MY_PIPE_TOKEN, useClass: MyPipe }
]
})
export class AppModule { }
In the component, use the service to get the right token:
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
constructor(private injector:Injector, private tokenService: TokenService){
let myInterface = injector.get(tokenService.getToken('myPipe'));
myInterface.transform('test');
}
}
Here's a stackblitz showing the updated example.
Upvotes: 1