Recently while building a new feature I found that moving logic out of the the .ts file into a pipe would make it far more re-usable in other components. The progression of this piece of work went under several revisions to reduce coupling and increase cohesion.
The initial logic looked something like this and was used to set the value of a public member ‘displayInfo‘ at ngOnChanges by calling getDisplayInfo
The value of displayInfo was then displayed in the .html file
1 | some-example.components.ts |
1 | some-example.components.html |
This worked however could be made better with a pipe as follows
1 | display-info.pipe.ts |
1 | display-info.module.ts |
The pipe was then imported as ‘DisplayInfoPipeModule’ into the module for my component in its module file some-example.module.ts This was then called in some-example.components.ts as follows
1 | some-example.components.html |
In my opinion this not only looks awkward but is not really how a pipe is intended to be used. It really should be seen as ‘hey sweetPrefixDisplayInfo take this value and format it’ the additional parameters could be to include additional formatting.
Example:
1 | {{ obj1.SomeDate | sweetPrefixDisplayInfo:includeTime }} |
However in my case we were creating a sentence string from three complex objects with rules to include parts of the sentence should valid objects be passed, these are the obj1, obj2 and obj3 objects.
As obj1, obj2 and obj3 are complex objects the pipe would not make use of all their properties, this is a code smell which is violating single responsibility and interface segregation principles.
The cleaner solution I feel would be to still use the pipe and introduce a new object specific to its function.
1 | export class DisplayInfoData { |
Then set a public property fooDisplayInfo in some-example.components.ts to the value of an instance of the type DisplayInfoData with the properties mapped from obj1, obj2 and obj3
Then call the pipe as:
1 | {{ fooDisplayInfo | sweetPrefixDisplayInfo }} |