12
votes

In a template-driven form I have two inputs. The second one comes from a ng-template.

<form #testForm="ngForm">
    First name <input type="text" name="firstName" [(ngModel)]="firstName" required> (required)
    <br>
    <ng-container *ngTemplateOutlet="inputTemplate"></ng-container>
</form>

The inputTemplate looks like this:

<ng-template #inputTemplate>
    Last name <input type="text" name="lastName" [(ngModel)]="lastName" required> (required)
</ng-template>

Both inputs have 'required' attribute, but form gets valid although the second input is empty.

Is there a way to ensure the input from the template is recognized by the form?

Demo: Plunker

Edit: In my real application, ng-template comes from another (3rd party) component and is loaded using template reference, see this Plunker.

I only found some solutions regarding parent-child component problems, but these were not practicable in this case.

3
Thanks, but both options not working in my real world application where <ng-template> comes from another (3rd party) component. However, in the same component it's working fine. Seems like I oversimplified the example in my question. Added additional information. Thank you. - fxmfr
The second option should work for you - yurzui
Can't get it work. Added viewProviders to component containing the form. Input is still added without being added to the form. Do you have a working example with a ng-template from another component? - fxmfr
ng-template comes from another (3rd party) Can you say what is the 3rd party library? - yurzui

3 Answers

1
votes

You cannot do that as an ng-template does not support @Inputs and @Outputs. I suggest you create a custom input component. Implement the ControlValueAccessor to achieve this - it will let you bind ngModel, set value, etc.

0
votes

I believe the problem is in Angular dependency injection. Your template is defined elsewhere and it uses Injector from where ever it is defined. Your form cannot know about it and your input doesn't know about the form, even though it is above it in DOM — it is not in Injector tree. If you would have access to template you could pass the form directive as context and use it in template to link input and form.

0
votes

Put ng-template#inputTemplate in the form, then it will work.

<form #testForm="ngForm">
    First name <input type="text" name="firstName" [(ngModel)]="firstName" required> (required)
    <br>
    <ng-container *ngTemplateOutlet="inputTemplate"></ng-container>

    <ng-template #inputTemplate>
    Last name <input type="text" name="lastName" [(ngModel)]="lastName" required> (required)
    </ng-template>
</form>