I have a component that I'm using like this in a different component:
<inline-help>
<help-title>{{::'lang.whatIsThis'|i18n}}</help-title>
<help-body i18n="lang.helpBody"></help-body>
</inline-help>
In inline-help
I'm using @ViewChild and ng-content to display the help-title
and help-body
.
@Component({
selector: 'inline-help',
template: `
<div class="inline-help">
<div class="help-icon">
<i class="en-icon-help"></i>
</div>
<div #helptext class="inline-help-text text-left">
<ng-content select="help-title"></ng-content>
<ng-content select="help-body"></ng-content>
</div>
</div>`
})
export class InlineHelpComponent implements AfterViewInit {
@Input() fixed: boolean;
@ViewChild('helptext', {static: false}) text: ElementRef;
......
What I want to do is create a new component like <inline-help-content>
that I can use as such inside :
@Component({
selector: 'inline-help',
template: `
<div class="inline-help">
<div class="help-icon">
<i class="en-icon-help"></i>
</div>
<inline-help-content [helpTitle]="something" [helpBody]="something"></inline-help-content>
</div>`
})
But I DONT want to change all the instances of
<inline-help>
<help-title>{{::'lang.whatIsThis'|i18n}}</help-title>
<help-body i18n="lang.helpBody"></help-body>
</inline-help>
that I use in other parts of the codebase, since that's a lot. Is it possible to parse the ViewChild and then get the text inside it and call another component to with the texts as inputs?
In your InlineHelpComponent
template, you can wrap the <ng-content>
s in elements with template reference variables assigned to them:
<div #helpTitle><ng-content select="help-title"></ng-content></div>
<div #helpBody><ng-content select="help-body"></ng-content></div>
Those template reference variables give you access to the native elements, so you can then pass the innerText
properties of those elements into your new InlineHelpContentComponent
(just be sure to hide the projected content in InlineHelpComponent
so it doesn't display twice). Here's what the InlineHelpComponent
template would look like:
<div class="inline-help">
<div style="display:none;">
<div #helpTitle><ng-content select="help-title"></ng-content></div>
<div #helpBody><ng-content select="help-body"></ng-content></div>
</div>
<inline-help-content
*ngIf="showInlineHelpContent"
[helpTitle]="helpTitle.innerText"
[helpBody]="helpBody.innerText">
</inline-help-content>
</div>
Here's a StackBlitz demonstrating this approach.
I found I had to include that *ngIf="showInlineHelpContent"
on the inline-help-content
component, and set the flag in ngAfterContentInit
after a setTimeout
, otherwise I was getting an ExpressionChangedAfterItHasBeenCheckedError
error.