angularangular-reactive-formsangular-formsform-control

Can you do a get(<path>) on an UntypedFormGroup if there is a '.' in the path parameter?


I have an Angular app that uses an UntypedFormGroup to store and retrieve input values from the user.

I add controls to the UntypedFormGroup using the addControl function like so:

this.myUntypedFormGroup.addControl('mypath', new UntypedFormControl());

and then retrieve the value like so:

this.myUntypedFormGroup.get('mypath').value

This works fine - except if I want to use a period in the path parameter.

For example, if I want the path to be the name of a pdf file:

this.myUntypedFormGroup.addControl('myfile.pdf', new UntypedFormControl());

It comes back with a null pointer exception when I try to retrieve it:

this.myUntypedFormGroup.get('myfile.pdf').value

I think I sort of understand why this is - it is interpreting the period in mypdffile.pdf to denote that 'pdf' is supposed to be a sub-control of 'myfile' and therefore it dies when it can't find a sub-control called 'pdf'.

Is there any way to do an escape on the period character such that it takes it as a literal part of the path string rather than assuming there is a sub-control?

Thanks much.


Solution

  • This problem is common for UntypedFormControl and FormControl.


    Why would you have a form control name as the file name, it should be defined as something easy to understand like file1 or myfilePdf, something like that.


    Instead you should store the name and file in a formArray so that you know from where it originated. There is no mandate that a form control should have a corresponding HTML, so you do not need a form field in HTML for fileName.

    ...
    new FormArray([
      new FormGroup({
        fileName: new FormControl('myFile.pdf'),
        file: new FormControl(null),
      })
    ])
    ...
    

    As far as I know, you cannot use . in the get method, since this is a convenient method in forms to drilldown to a nested controlName deep inside the form. E.g:form.get('address.line1').value


    You can write a method that does base64 encoding and access it, but I don't think it's worth the effort.

    ...
    export class App {
      form = new FormGroup({
        [this.controlNameAllowDots('my-file.pdf')]: new FormControl(null),
      });
    
      ngOnInit() {
        debugger;
        console.log(this.form.get(this.controlNameAllowDots('my-file.pdf'))!.value);
      }
    
      controlNameAllowDots(name: string) {
        return btoa(name);
      }
    }
    

    Stackblitz Demo