How to pass a string to a custom pipes constructor

78 Views Asked by At

I'm trying to create a re-usable pipe that takes a string in it's constructor. But I can't figure out how to get it to work.

I get an error on the constructor parameter: No suitable injection token for parameter 'replacement' of class 'CustomBooleanPipe'. Consider using the @Inject decorator to specify an injection token.(-992003) custom-boolean.pipe.ts(8, 28): This type is not supported as injection token.

Here is the custom pipe:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'customBoolean',
  standalone: true
})
export class CustomBooleanPipe implements PipeTransform {
  private replacement: string;
  constructor(replacement: string) {
    this.replacement = replacement;
  }
  transform(object: any, keyName: string, ...args: unknown[]): string {
    return object[keyName] ? this.replacement : '';
  }
}

The pipe is put in an object and passed to child components through an input variable, and used in the html.

<div *ngFor="let column of gridColumns" [matColumnDef]="column.name">
  <th mat-header-cell *matHeaderCellDef> {{ column.name }} </th>
  <td mat-cell *matCellDef="let element; let i = index" class="compact-form" [ngClass]="column.style">
    <div> {{ column.dataPipe ? column.dataPipe.transform(element, column.dataKey) : element[column.dataKey] }}</div>
  </td>
</div>

gridColumns is the input variable of type IGridColumn[]

export interface IGridColumn {
  name: string;
  dataKey: string;
  style?: string;
  dataPipe?: PipeTransform
  sortKey?: string;
  sortOrder?: SortDirection;
}
gridColumns: IGridColumn[] = [
  {
    name: 'Beta',
    dataKey: 'betafeature',
    style: 'emphasized-cell',
    dataPipe: new CustomBooleanPipe('BETA')
  },
  {
    name: 'Paid',
    dataKey: 'paidfeature',
    style: 'emphasized-cell',
    dataPipe: new CustomBooleanPipe('$')
  }
];
1

There are 1 best solutions below

0
On

Its much simpler to pass it as an input to the transform method, since it reduces the number of objects created and you can vary the input based on the params being sent. Please check the below example!

pipe

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'customBoolean',
  standalone: true,
})
export class CustomBooleanPipe implements PipeTransform {
  constructor() {}
  transform(object: any, keyName: any, replacement: any, ...args: any[]): any {
    console.log(object, keyName, replacement);
    return object[keyName] ? replacement : '';
  }
}

ts

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { CustomBooleanPipe } from './custom-boolean.pipe';
import { MatTableModule } from '@angular/material/table';

export interface IGridColumn {
  name: string;
  dataKey: string;
  style?: string;
  dataPipeParam: string;
  sortKey?: string;
  sortOrder?: any;
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CustomBooleanPipe, MatTableModule, CommonModule],
  template: `
    <table mat-table [dataSource]="dataSource" class="mat-elevation-z8">

  <!--- Note that these columns can be defined in any order.
        The actual rendered columns are set as a property on the row definition" -->

  <!-- Position Column -->
    <ng-container *ngFor="let column of gridColumns" [matColumnDef]="column.name">
      <th mat-header-cell *matHeaderCellDef> {{ column.name }} </th>
      <td mat-cell *matCellDef="let element; let i = index" class="compact-form" [ngClass]="column.style">
        <div> {{ element | customBoolean : column.dataKey : column.dataPipeParam }}</div>
      </td>
    </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

  `,
})
export class App {
  displayedColumns: string[] = ['Beta', 'Paid'];
  dataSource = [{ betafeature: 'test' }, { paidfeature: 'test2' }];
  gridColumns: IGridColumn[] = [
    {
      name: 'Beta',
      dataKey: 'betafeature',
      style: 'emphasized-cell',
      dataPipeParam: 'BETA',
    },
    {
      name: 'Paid',
      dataKey: 'paidfeature',
      style: 'emphasized-cell',
      dataPipeParam: '$',
    },
  ];
}

bootstrapApplication(App);

stackblitz