Angular pipes: Custom - lordoftheflies/angular-essential-training GitHub Wiki
Creating your own custom pipes in Angular is fairly trivial. Basically involving a decorator with a bit of metadata and a known method signature on a class. Let's build a custom pipe for the application that will display a list of all the unique media item categories for the media items currently displayed on the screen. We start by creating a new file named category-list.pipe.ts in the app folder. We need to use the pipe decorator which is in the Angular core scoped package. So, let's import that. And then add @pipe with a parenthesis. The pipe decorator accepts an object of metadata, similar to component and directive decorators. There are two properties available, name and pure. We use an object literal and we set name to a string value of categoryList. This is the name we use in our templates. The other property, pure, helps define if a pipe is stateless or stateful. Pure means that the pipe will take in data and will return data without any side effects. Just like pure functions. Pipes are pure, or stateless, by default and this metadata property is optional. Our pipe will be stateless so we don't need to include that metadata property. After the decorator call, we need to have a class. So, we add export class CategoryListPipe. Just like components and directives, you will need to import pipes you create into other files to use them, thus the export of the class. Next we need to implement a transform method. Angular calls a method with a name transform on a pipe class and it will pass the pipe argument, or value being piped to it, as the first parameter. We can make use of a TypeScript interface here to help enforce this usage. The pipe transform interface. Let's import that from Angular core as well. And then we can use the key word implement after the class name and then a space and then the pipe transform interface. With that in place, we can create a class method named transform. If the pipe has parameters, the values after the colons in the template, it will pass those in as parameters in list form after the first argument. Let's make use of the value parameter. So, we add a parameter named mediaItems. The parameter name can be whatever we want. Only the method name has to be what Angular is expecting. Okay, now we can fill out the logic of the transform method. We want to get all the distinct category names across all media items passed in. Let's just add a pre-written sample block of code to do that logic on an array. I'm going to copy this code from a sample.txt file that has already been added to the project for this lesson. And I'll paste that into the transform method. This code sets up a local array to store the unique category names found, uses the array .forEach method to walk over the collection and add unique names to the local array. Then it returns the local array values, joined into a string with a comma separator. One thing to note here, is we are returning a string value from the pipe. But that is not a requirement. You can build pipes that return other data types and Angular will just flow that through. It really just depends on how you are intending to use that pipe. Okay, let's use the new pipe we created. In the media-item-list.component.html file, let's add a header element. And in there, let's add a div with the interpolation syntax of double curly braces mediaItems. Then add the pipe character, followed by the name we use for the category list pipe decorator metadata, categoryList. The last step we need to do, is tell Angular to add our custom pipe to the app module. Over in the app module ts file, we can add an import statement to bring in the category list pipe type. And then add the type to the declaration's metadata property array, remembering that the declarations property is for components, directives, and pipes to be used in the module. Now, if we head over to the browser, we can see the list of unique categories rendered from the custom pipe.