lacolaco / ng-dynamic

dynamic contents projection in Angular

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Custom Pipes

HFTSOL opened this issue · comments

Good day,

First I'll say thank you so much for this directive. It has been a life saver thus far. I have been doubting mt decision to go with NG2 because of the horrible decisions they have been making when removing certain features, and this directive gives me back atleast one feature that is missing.

With that said, I am having an issue with using custom pipes. I have the DynamicComponentModule imported into my SharedComponentsModule and am importing the requisite components into it.

Example

Shared Module

@NgModule({
    declarations: [
        StringDatePipe,
        WidgetComponent
    ],
    imports: [
        GridModule,
        DynamicComponentModule.forRoot({
            imports: [
                GridModule
            ]
        })
    ],
    exports: [
        StringDatePipe,
        WidgetComponent
    ]
})

export class SharedComponentsModule {
    static forRoot(): ModuleWithProviders {
        return <ModuleWithProviders> {
            ngModule: SharedComponentsModule,
            providers: []
        };
    }
}

Widget Component

@Component({
    selector: 'widget',
    encapsulation: ViewEncapsulation.None,
    template: '<div *dynamicComponent="gridHtml; context: {gridData:config.data};"></div>'
})
export class WidgetComponent {
    @Input() public config: IGridPanelConfig;

    gridHtml: string = '';

    constructor(private _templateWriter: DynamicTemplateWriterService) {}

    ngOnInit() {
        this.gridHtml = this._templateWriter.writeGridTemplate(this.config.gridOp);
    }
}

Custom Pipe

@Pipe({name: 'stringdate'})
export class StringDatePipe implements PipeTransform {
    transform(value: string, format?: string): string {
        console.log('StringDatePipe: ' + value);
        try {
            return this.formatDate(new Date(value), format || 'MM/dd/yyyy');
        }
        catch (ex) {
            console.log(ex);
        }

        return '';
    }

    private formatDate(date: Date, format: string = "MM/dd/yyyy"): string {
        // Parses string into Date and returns in specified format
    }
}

Dynamic Template Writer

@Injectable()
export class DynamicTemplateWriterService {
    public writeGridTemplate(cfg: IGridOptions): string {
        console.log('writeGridTemplate');
        let html = '';
        // Compose grid HTML
        return html;
    }
}

If I write out the template without the pipe, everything works fine. If I write the template with the pipe, it writes the template html as expected, but Angular doesn't render the grid and no errors are thrown. Also, the console.log() in the custom pipe's transform function is never run.

I have tested the pipe, and it works fine in components not written with the ng-dynamic directive; so I'm led to believe that the pipe doesn't exist inside the ng-dynamic directive, but I'm not sure how to share the pipe with the directive.

Thanks in advance for any assistance.

Ok, so I worked on this issue for 6 hours yesterday and made no real progress. I spent the time to post this question here with sample code, and then spent another few hours googling... then... it dawned on me to put the pipes in a sub-module and import it into both the SharedComponentsModule and the DynamicComponentModule.... and it's all working now...

I feel so dumb...!

Here's the sample solutions for future dumbies like me.

Shared Module

@NgModule({
    declarations: [
        WidgetComponent
    ],
    imports: [
        PipesModule,
        GridModule,
        DynamicComponentModule.forRoot({
            imports: [
                PipesModule,
                GridModule
            ]
        })
    ],
    exports: [
        WidgetComponent
    ]
})

export class SharedComponentsModule {
    static forRoot(): ModuleWithProviders {
        return <ModuleWithProviders> {
            ngModule: SharedComponentsModule,
            providers: []
        };
    }
}

Pipes Module

@NgModule({
    declarations: [
        StringDatePipe
    ],
    exports: [
        StringDatePipe
    ]
})
export class PipesModule {
}

Side note: I am still unable to get the out of the box pipes to work, so I'm putting versions of those in my pipes module for the dynamic components to use. Please let me know if there's a better way to do this.

To import any directives/pipes, NgModule is needed (for compilation). your solution is not a workaround but a right way.
Thanks