I have a MatStepper
that’s used to navigate to the next page of a signup flow. I also have a method that loads values from a cache if it’s available, and if so then the MatStepper
skips to Page 2. After that, a future method pre-fills the form will those cached values.
The scenario where cachedSports
are retrieved causes the MatStepper
to work and skip to Page 2, but when I try to pre-fill with cachedPets
or cachedAnimals
the MatStepper
fails and gives me the following error:
Cannot read properties of undefined (reading 'next')
There aren’t a lot of differences between cachedSports
and the two failing scenarios, so I don’t know what the culprit is. All three are arrays of strings and the values from their caches are coming in successfully.
// Cached values are retrieved from another file, memory-cache.service.ts
loadFromCache(): void {
const cachedPets: string[] = this.cacheService.get<string[]>(MemoryCacheService.WellKnownKeys.pets) ?? [];
const cachedSports: string[] = this.cacheService.get<string[]>(MemoryCacheService.WellKnownKeys.sports) ?? [];
const cachedAnimalNames: string[] = this.cacheService.get<string[]>(MemoryCacheService.WellKnownKeys.animals) ?? [];
// Note that cachedPets and cachedAnimalNames share ('targetEveryAnimal')
if (cachedPets.length > 0) {
this.targetingFormGroup.get('targetEveryAnimal').setValue('Specific');
this.targetPetChange({ value: 'Specific' }, cachedPets);
} else if (cachedSports.length > 0) {
this.targetingFormGroup.get('targetEverySport').setValue('Specific');
this.targetSportChange({ value: 'Specific' }, cachedSports);
} else if (cachedAnimalNames.length > 0) {
this.targetingFormGroup.get('targetEveryAnimal').setValue('Specific');
this.targetAnimalChange({ value: 'Specific' }, cachedAnimalNames);
}
// The values correctly come through:
console.log('cachedPets: ', cachedPets); // ["Cat"]
console.log('cachedSports: ', cachedSports); // ["Tennis"]
console.log('cachedAnimalNames: ', cachedAnimalNames); // ["Chinchilla"]
this.goForward();
this.location.replaceState('filters/setup/create/page2');
this.skipPageOne = true;
this.cacheService.remove(MemoryCacheService.WellKnownKeys.pets);
this.cacheService.remove(MemoryCacheService.WellKnownKeys.sports);
this.cacheService.remove(MemoryCacheService.WellKnownKeys.animals);
}
goForward(){
this.myStepper.next();
// Defined as: @ViewChild('stepper') private myStepper: MatStepper;
}
This is where the cached values are actually added into the form
// Same file as the above code
validateFormTargeting() {
const sports = (spt === 'Specific') ? this.targetingFormGroup.get('sports').value : [];
console.log('tfg-sports: ', this.targetingFormGroup.get('sports').value) // ["Tennis"]
console.log('sports: ', sports) // ["Tennis"]
let pets;
let animalNames;
if (animt === 'Specific') {
// pets = this.tarFormGroup.get // etc
animalNames = this.targetingFormGroup.get('animalNames') ? this.targetingFormGroup.get('animalNames').value : [];
// The console messages (therefore this code block) is not reached because of the "Cannot read properties of undefined" error
console.log('tfg-animalNames: ', this.targetingFormGroup.get('animalNames').value)
console.log('animalNames: ', animalNames)
}
}
Verbose err message:
TypeError: Cannot read properties of undefined (reading 'next')
at AppModalFormCreateComponent.goForward (myForm.component.ts:371:20)
at AppModalFormCreateComponent.loadFromCache (myForm.component.ts:357:10)
at AppModalFormCreateComponent.ngOnInit (myForm.component.ts:227:10)
Advertisement
Answer
It’s the ViewChild
not being defined/set when goForward
is called.
If the template is being updated then it’s probably a timing issue. For testing purposes you can wrap the code in goForward
in a setTimeout()