6

I am running into an issue where I'm trying to use UI elements before they've completely loaded, resulting in undefined exceptions.

The form is loaded in the components constructor, and then I call the initializeElements method to work with the UI elements. However, as I mentioned I'm getting null and undefined exceptions because I suspect the loadForms() method is not completely finished when I go to get the objects.

I'm new to angular, so I'm not sure what I can do here to 'wait' until the form is completely loaded. I've tried placing the methods in a few different lifecycle hooks but have not had any success.

I have my component:

export class UIComponent implements OnInit{
    form = new FormGroup({});
    model = {};
    fields: FormlyFieldConfig[];

    constructor(){
        this.fields = loadForm();

        this.initializeElements();
    };

    ngOnInit(){
    }; 


    initializeElements(){
        var overrides = this.form.get('Overrides'); // this is null on page load
        var firstNameObj = overrides.get('First Name'); // also null on page load
    };
}

My component template:

<form fxLayoutAlign="center center" [formGroup]="form">
    <formly-form [form]= "form" [fields]="fields" [model]="model"></formly-form>
</form>

The method loadForms:

export function loadForms(){
    return [
               {
                   'key': 'Overrides',
                   'fieldGroup': [{
                   'fieldGroupClassName': 'display-flex',
                   'fieldGroup': [{
                                     'key': 'First Name',
                                     'type': 'input',
                                     'value': 'New First Name',
                                     'templateOptions':{
                                          'label': 'First Name: '
                                      }
                                 },
                                     'key': 'Last Name',
                                     'type': 'input',
                                     'value': 'New Last Name',
                                     'templateOptions':{
                                          'label': 'Last Name: '
                                     }
                                 }]
                    }]
               }
          ]
}
Martelyn
  • 83
  • 1
  • 5

2 Answers2

11

Take a look to lifecycles: https://angular.io/guide/lifecycle-hooks

If you use loadForms() in your constructor() method, it won't wait the view to load. For this, if you want to make sure your view finished loading, use ngAfterViewInit().

Please, if it is possible, don't load your data or call methods on the constructor, use ngOnInit, ngAfterViewInit() or any of the lifecycle hooks listed on the docs above as needed.

I don't know if you used them, in case you tried with ngAfterViewInit() and it didn't work try setting an *ngIf=fields on your <form> tag

Hope it helps.

Pablo Navarro
  • 442
  • 3
  • 13
0

you could create an observable

export class UIComponent implements OnInit{
    form = new FormGroup({});
    model = {};
    overrides: any;
    firstNameObj: string = '';
    fields: FormlyFieldConfig[];

    constructor(){
    };

    ngOnInit(){
        loadForm().subscribe(
        response => {
           this.fields = response;
           this.initializeElements();
        }
    }; 


    initializeElements(){
        overrides = this.form.get('Overrides'); // this is null on page load
        firstNameObj = overrides.get('First Name'); // also null on page load
    };
}

then your export function would look something similar to this. I assume this is in its own file so there might be a little discrepancy to how this should be. but if this is going to be changed from a function to http service call, the observable should stay the same.

export function loadForms (): Observable<any> => {
  return new Observable<any>(observer =>{
    observer.next([
      {
        'key': 'Overrides',
        'fieldGroup': [{
          'fieldGroupClassName': 'display-flex',
          'fieldGroup': [{
            'key': 'First Name',
            'type': 'input',
            'value': 'New First Name',
            'templateOptions':{
            'label': 'First Name: '
            }
          },
          {
            'key': 'Last Name',
            'type': 'input',
            'value': 'New Last Name',
            'templateOptions':{
              'label': 'Last Name: '
            }
          }]
        }]
      }
  ]);
}
rhavelka
  • 2,283
  • 3
  • 22
  • 36