0

The problem: either I can have the custom control render values of the bound ngModel or I can have the validation "bubble up" as expected.

My custom text component has a required attribute which is respected on that layer but the parent doesn't know about it unless I use a viewProvider. however when Using the viewProvider, I don't have anything render.

I've created a stackblitz with an running example of what I mean. Please find the custom-text component and try the form with the viewProvider commented and un commented.

https://stackblitz.com/edit/angular-fail-to-render

Id love to understand what I'm doing wrong and how to achieve this communication between the form and custom control.

Jessy
  • 1,150
  • 16
  • 27
  • I've attempted solutions that do not use `viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],` however without this I"m not seeing any kind of communication of the custom form component. it's ngModel is undefined. – Jessy Feb 13 '19 at 20:10

1 Answers1

1

from this response add provide: NG_VALIDATORS, remove required and add a validatiton function like

public setDisabledState?(isDisabled: boolean): void { }
validate(control:any){
    return this.model?null:{required:true}
  }

your forked stackblitz

Update There are a problem when we using an array of string (or an array of numbers) with [(ngModel)].

This not work

  {{model.loopValues|json}}
  //NOT WORK
  <div *ngFor="let n of model.loopValues; let i = index;">
    <input [(ngModel)]="n" 
        name="{{'ct'+i}}" #control="ngModel"></custom-text>
  </div>

And not work because the ngModel is binding over the temporally variable "n". If model.loopValues was an array of object this work because is binding over the "memory position" of the object.

We can think about this

  //NOT WORK
  <div *ngFor="let n of model.loopValues; let i = index;">
    <input [(ngModel)]="model.loopValues[i]" 
          name="{{'ct'+i}}" #control="ngModel"></custom-text>
  </div>

And not work because, when we change the input, lost the focus because Angular render again the *ngFor

My Idea is in .ts has an array of the same length of the model.loopValues

  array=new Array(this.model.loopValues.length)

And now we can do

<div *ngFor="let n of array; let i = index;">
    <custom-text [(ngModel)]="model.loopValues[i]" 
      name="{{'ct'+i}}" #control="ngModel"></custom-text>
</div>

BONUS: We can use a repeat directive and write some like

<div *repeat="model.loopValues.length;let i">
    <custom-text [(ngModel)]="model.loopValues[i]" 
      name="{{'ct'+i}}" #control="ngModel"></custom-text>
</div>
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Thanks for this tip! I'll be going over the validate method and seeing if it works in my actual codebase. My scenario is a bit more complex then just this stackblitz example :) – Jessy Feb 13 '19 at 16:26
  • https://angular.io/api/forms/Validator and https://angular.io/api/forms/NG_VALIDATORS have examples based on your suggestion :) I think this will work fine, thanks for pointing this out ! – Jessy Feb 13 '19 at 17:08
  • 1
    don't work with a normal input too. (sorry It's late now, If I get some time, I'll try to know why it's happens) – Eliseo Feb 13 '19 at 22:59
  • I appreciate it :) I keep hitting into these strange scenarios with Angular that end up in many hours of research and trial and error. – Jessy Feb 13 '19 at 23:11
  • I update my answer trying explain why ngModel and the arrays of strings cause problems. NOTE: It's not official, it's only my personal opinion about this theme – Eliseo Feb 13 '19 at 23:52