I have created a custom component that has many input properties. However, one thing I have noticed when using this component is that many of the input properties are the same within the parent component.
An example usage looks like this:
<yes-no
controlName="isAwesome"
labelKeyBase="MODULE.PAGE_X"
validationKeyBase="VALIDATION.CUSTOM_X"
someOtherProp="true"
></yes-no>
I have been using a library called transloco and noticed some functionality that would be very useful in this situation. Unfortunately, I have no idea how it would be implemented.
https://ngneat.github.io/transloco/docs/translation-in-the-template#utilizing-the-read-input
I'm wondering if there is a simplified example out there that demonstrates how to pass a value from a parent directive to a child component. Basically, my goal is to turn the above code into something like this:
<ng-container *yesNoConfig="labelKeyBase: 'MODULE.PAGE_X'; validationKeyBase: 'VALIDATION.CUSTOM_X'">
<yes-no controlName="isAwesome"></yes-no>
<yes-no controlName="isClean"></yes-no>
<yes-no controlName="isShort"></yes-no>
</ng-container>
CodePudding user response:
That looks like a custom *ngFor
, and the t
is likely a higher order function passed to the de-sugared ng-template
as the $implicit
value in the context
There's a good example to follow and get started with here:
The code for that transloco
directive is also on GitHub
CodePudding user response:
Here's a directive that applies arbitrary attributes to all immediate children of the container:
@Directive({
selector: '[setAttributes]',
})
export class SetAttributesDirective {
@Input('setAttributes') atts: { [key: string]: string } = {};
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef
) {}
ngOnInit() {
const keys = Object.keys(this.atts);
const viewRef = this.viewContainer.createEmbeddedView(this.templateRef);
for (const node of viewRef.rootNodes) {
if (typeof node.setAttribute !== 'function') continue;
const el = node as HTMLElement;
for (const key of keys) el.setAttribute(key, this.atts[key]);
}
}
}
Not very typesafe since viewRef.rootNodes
is type any[]
but what can you do... I put somewhat of a typeguard anyway. The first entry is actually the ng-container
itself, and nested templates / ng-containers will also not have a setAttribute
function, throwing an error without the typeguard. Could definitely be improved, but at least you get the gist.
You'd use it like this:
<ng-container *setAttributes="{ type: 'number', value: '5', min: '0', max: '10' }">
<input />
<input />
<input />
<input />
</ng-container>
Associated docs: https://angular.io/guide/structural-directives
Stackblitz example: https://stackblitz.com/edit/angular-ivy-1eyjlo?file=src/app/app.component.html
Your specific example
<ng-container *setAttributes="{ labelKeyBase: 'MODULE.PAGE_X', validationKeyBase: 'VALIDATION.CUSTOM_X' }">
<yes-no controlName="isAwesome"></yes-no>
<yes-no controlName="isClean"></yes-no>
<yes-no controlName="isShort"></yes-no>
</ng-container>