Wrapping content children in a dynamic parent tag with Angular 2
What I want to do
I want to create a reusable Angular 2 button component that may render as an <a />
tag or an <input />
tag depending on an input to the component called type
. I want the button component to accept content children which will be rendered as the button label.
To illustrate: an Angular template that invokes my button
component like so:<button>Hello</button>
should render as <a>Hello</a>
in the DOM. However, if a property type="submit"
is set (e.g. <button type="submit>Hello</button>
) then the output in the DOM should be <input type="submit">Hello</input>
.
To further clarify, if I were using React I could create [an overly simplified version of] this component with:
const Button = ({ type, children }) =>
type === "submit"
? <input type="submit">{children}</input>
: <a>{children}</a>
Where I'm stuck
Creating an Angular component that displays content children using <ng-content />
was relatively straightforward. However, I'm yet unable to render those children inside a dynamically chosen tag - either <a />
or <input />
depending on the value of the type
property.
What I've tried
I initially tried to use <ng-content />
inside an ngIf
or ngSwitch
directive, only to find out that <ng-content />
can appear at most once in any given template (unless it’s qualified with a selector). However, I want to output all content children so selectors are not helpful.
I keep finding references to DynamicComponentLoader, but that appears to be deprecated.
I've seen the ContentChildren decorator which would allow my button component to access the content children being passed to it, but I'm not sure how to then take those children and inject them into my component template.
I came across NgTemplateOutlet, which seems like it might help me switch between two entirely different templates (one w/ the <a />
tag and one with the <input />
tag). However that's marked as “Experimental” and I’m having trouble understanding the usage.
Any help would be greatly appreciated!!
@Component({
selector: 'adapting-button',
template: `
<a *ngIf="type !== "submit">{{value}}</a>
<input *ngIf="type === "submit" type="submit" [value]="value">
`,
})
export class AdaptingButtonComponent {
@Input() type: any;
@Input() value: any;
}
@Component({
selector: 'app-root',
templateUrl: `
<adapting-button [type]="'submit'" [value]="Hello"></adapting-button>
`,
})
export class AppComponent {
title = 'app works!';
}