On many occasions, we need to write text strings in our Angular templates.
The two most common solutions (or at least those that I have found in the projects I have worked on) are the following:
- Write the value of the variable directly in the template:
foo-component.component.html
<img [src]="'path/to/my/resource.png'">
<div> THIS IS A FOO TITLE </div>
This form presents the problem that the constants are not unified and, in the future, if we want to change the values of these, we must search for the content of the literals and replace them with each occurrence.
- Write the constants in a separate file, import it and declare it as a variable in the component in order to use it:
my-collection-of-constants.ts
export const Foo = {
foo: 'foo',
resource: 'my/foo/file.png'
}
my-component.component.ts
@Component(
...
)
export class MyComponent {
public foo = Foo;
...
public getFooValueByKey(key: string) {
return this.foo[value];
}
}
my-component.component.html
<div> {{ getFooValueByKey('foo') }} </div>
<img [src]="foo.resource">
Through this solution, we unify the value of the constants , all right!.
However, we will dirty the component with the declaration of multiple variables and methods whose only purpose is to display text.
Proposed solution: use Pipes
In order to prevent hardcoding in templates and the declaration of unnecessary variables in components, the following solution based on Angular Pipes is proposed:
- Generate a file that contains an object with the values to be used or displayed:
hardcoded-values.ts
export const hardcodedValues = {
pasta: 'An awesome pasta dish',
pizza: 'The most tasty pizza ever',
dessert: 'Icecream, cupcakes... and more!'
}
- Create our Pipe in the following way.
prevent-hardcoding.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { hardcodedValues } from './hardcoded-values.ts';
@Pipe({
name: 'preventHardcoding'
})
export class PreventHardcodingPipe implements PipeTransform {
transform(value: any, args?: any): any {
if (value in hardcodedValues) {
return hardcodedValues[value];
} else {
console.error(
`
No properly value set for key '${value}'.
Please, check available keys.
Feel free to add new one if you need.
`
);
return undefined;
}
}
}
If you look closely at the transform method, what it will do is check if the value of the key value and, if so, return the associated value.
All right! Now we can use our Pipe to use values housed in the hardcodedValues object.
app.component.html
<!-- Display value in template -->
<div> {{ 'pasta' | preventHardcoding }} </div>
<!-- As @Input for component -->
<app-foo
[someInput]="'pizza' | preventHardcoding">
</app-foo>
With the use of this pattern, we were able to decouple the value of the text strings, numbers … of each component. Thus, any change in the displayValues object will propagate to each component that makes use of the preventHardcoding Pipe.
Top comments (0)