0

I have a form to add projects and repos for those projects. When adding a repo, you enter a POM URL. I am having trouble with accessing the POM URLs and it is preventing the form from loading.

I get the error "Cannot read property 'controls' of null

(The code is on another computer, so I'll recreate it the best I can)

TS

this.addProject = new FormGroup({
  ...
  repos: new FormArray([
    new FormGroup({
      ...
      pomUrls: new FormArray([new FormControl()])
    })
  ])
});

addRepo(): void {
  this.addRepos.push(new FormGroup({
    ...
    pomUrls: new FormArray([new FormControl()])
  }));
}

get addRepos(): FormArray {
  return this.addProject.get('repos') as FormArray;
}

get pomUrls() {
  return this.addRepos.get('pomUrls') as FormArray;
}

addPomUrls() {
  const control = new FormControl();
  this.pomUrls.push(control);

removePomUrl(index: number): void {
  this.pomUrls.removeAt(index);
}

HTML

<ng-container formArrayName="pomUrls">
  <div *ngFor="let _ of pomUrls.controls; index as i; count as c;">
    <las-ux-textfield [label]="'POM URLs'" [formControlName]="i"></las-ux-textfield>
    <div clss="button-container">
      <las-ux-button [id]="'addPom' + i" ... (click)="addPomUrls()"> </las-ux-button>
      <las-ux-button *ngIf="c > 1" [id]="'removePom' + i" ... (click)="removePomUrl(i)"> </las-ux-button>
    </div>
  </div>
</ng-container>

So as-is, this gives me the "cannot read property 'controls' of null" error

If I change get pomUrls to the following --

get pomUrls() {
  return this.addRepos.at(0).get('pomUrls') as FormArray;

-- then it works perfectly...at least for retrieving at index 0. With this, I can add multiple pomUrls for a single repo, or add multiple repos with a single pomUrl.

BUT I can't add multiple repos with multiple pomUrls. Then it gives me an error "cannot find control with path: 'repos -> 1 -> pomUrls -> 1'". So it can't go beyond index 0, which makes sense.

My question is WHY I can't get this to work? Why does addRepos.at(0).get('pomUrls') work but addRepos.get('pomUrls') doesn't?

This is my first big project with Angular and I've been stuck on this for a week. I have been searching for help, wording this every way I can think of, and read through a lot of articles and other questions here on stackoverflow, but no luck.

Any help is greatly appreciated!

2 Answers 2

1

Please add ? to pomUrls?.controls in your template html.

pomUrls is undefined at some point in runtime.

?. is a null safety operator

Sign up to request clarification or add additional context in comments.

1 Comment

This gets rid of the console error, but then the pomUrls textfield doesn't appear on the page. Any thoughts on why or how to fix it?
0

About the problem

The easiest way to understand how this works is to visualize the value of the FormGroup

Below is how your FormGroup for addProject will look like

  {
    repos: [
      {
         pomUrls: ['']
      }
    ]
  }

and this is for addRepos

 [
   {
      pomUrls: ['']
   }
 ]

Now consider the below code

  return this.addRepos.at(0).get('pomUrls') as FormArray;

The above code takes the first item (.at(0)), and extracts the pomUrls property. Basically, if this was a simple JS code it would be myFormGroup[0].pomUrls. as you have mentioned this works perfectly.

Now lets try this code

  addRepos.get('pomUrls')

Now the above is like trying to do the below

  const addProject =   {
repos: [
  {
     pomUrls: ['']
  }
]
  }
  const addRepos = addProject.repos;
  console.log(addRepos.pomUrls)

So generally its like trying to extract a property from an array without getting a specific index first

How to resolve?

You can use many ways to approach this. You can consider below

getPomUrls(i) {
  return this.addRepos.controls[i].get('pomUrls') as FormArray;
}

In the above instead of setting pomUrls as a getter, use a function that takes in an argument of the index

Edit 1

Since we have removed pomUrls your addPomUrls will also have to change

    addPomUrls(i) {
      const control = new FormControl();
      this.getPomUrls(i).push(control)
    }

Basically we are adding a pomUrls for a specific index of project

2 Comments

making the above change stops addPomUrls() from working (and a removePomUrl() I didn't include in the original question). It no longer works because property 'push' (and 'removeAt') don't exist on type '(i: any) => FormArray'. Would there be a different way to do my add and remove functions? I added the remove function to my original question so you can see it too
Thank you for adding in how to change addPomUrls accordingly. Unfortunately, now getPomUrls is triggering "Cannot read property 'get' of undefined" error. I can't figure out why this.addRepos.controls[i] would be considered undefined?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.