12

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.

fxmfr
  • 171
  • 1
  • 7
  • 1
    https://stackoverflow.com/questions/46849570/cloned-elements-cannot-be-submitted-in-angular4/46863758#46863758 – yurzui Nov 07 '17 at 10:58
  • Thanks, but both options not working in my real world application where 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 Nov 07 '17 at 13:33
  • The second option should work for you – yurzui Nov 07 '17 at 13:35
  • 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 Nov 07 '17 at 16:14
  • `ng-template comes from another (3rd party) ` Can you say what is the 3rd party library? – yurzui Nov 07 '17 at 16:18
  • Yes, sure. It's primeng datatable. I access property #datatable.columns[].editorTemplate to get the template. – fxmfr Nov 10 '17 at 08:36
  • Did you solve this problem? – benshabatnoam Dec 03 '18 at 13:12
  • @benshabatnoam No, I didn't, sorry. Switched to reactive forms as a workaround. – fxmfr Dec 03 '18 at 15:02
  • @yurzui IMO you should be flagging as duplicate rather than posting a link to your answer as a comment. – Dane Brouwer Aug 24 '21 at 07:50

3 Answers3

2

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.

2

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>
Gray Young
  • 41
  • 4
0

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.

waterplea
  • 3,462
  • 5
  • 31
  • 47
  • "pass the form directive as context and use it in template to link input and form" - Any idea how exactly? Say with `
    `.. `` or `context: {$implicit: form}`..
    – quentin-starin Oct 11 '19 at 17:53
  • Second one. Context should be an object with $implicity key so you can use it in template later like that: `` and pass it to formGroup inside template. – waterplea Oct 18 '19 at 12:33
  • Can either of you elaborate a little further for those with less understanding of Angular? Perhaps a working Stackblitz? – Dane Brouwer Jan 21 '20 at 14:04