#Undefined service despite using DI

31 messages · Page 1 of 1 (latest)

tight pumice
#

Hello,
the FormControl validators are implemented as a service, as they must use other custom services, which serve the error messages. Somehow the service injected in the Validation service is undefined, and I have no idea what is going on...

ERROR TypeError: Cannot read properties of undefined (reading '_linkErrorMessageService'
export interface ErrorMessageService<T> {
  getMessaghe(key: T): ValidationErrors;
}
@Injectable({
  providedIn: 'root',
})
export class LinkErrorMessageService implements ErrorMessageService<LinkErrorKeys> {
  getMessaghe(key: LinkErrorKeys): ValidationErrors {
    return { key: linkErrors[key] };
  }
}
@Injectable({
  providedIn: 'root',
})
export class LinkValidationService {
  constructor(private _linkErrorMessageService: LinkErrorMessageService) {}

  validUrlFormat(control: AbstractControl): ValidationErrors | null {
    if (control.value) {
      const error: ValidationErrors = this._linkErrorMessageService.getMessaghe(LinkErrorKeys.invalidUrl);   //undefined
      try {
        new URL(control.value);
        const topLevelDomainRegex: RegExp = /.\../;
        if (!topLevelDomainRegex.test(control.value)) {
          return error;
        }
      } catch (e) {
        return error;
      }
    }
    return null;
  }
bold blade
#

So

#

This seems to be an issue with this.

#

The injected service isnt undefined.

#

Cannot read properties of undefined (reading '_linkErrorMessageService'

#

You are trying to read a property on undefined

#

Based on the code, I'd assume its this._linkErrorMessageService, which is a bit odd.

#

I assume u are using this validUrlFormat somewhere like this: linkValidationService.validUrlFormat

#

without calling it, but setting it as a validator

#

The solution is to avoid that.

#

But use (control) => linkValidationService.validUrlFormat(control)

#

or, make validUrlFormat a property rather than a method:

#
  validUrlFormat = (control: AbstractControl): ValidationErrors | null => {
    if (control.value) {
      const error: ValidationErrors = this._linkErrorMessageService.getMessaghe(LinkErrorKeys.invalidUrl);   //undefined
      try {
        new URL(control.value);
        const topLevelDomainRegex: RegExp = /.\../;
        if (!topLevelDomainRegex.test(control.value)) {
          return error;
        }
      } catch (e) {
        return error;
      }
    }
    return null;
  }
#

Alot of assumptions tho, so I could be wrong 😄

tight pumice
#
    this.linkForm = new FormGroup({
      [NewLinkFields.destinationUrl]: new FormControl(null, {
        validators: [_linkValidationService.validUrlFormat],
        updateOn: 'blur',
      }),
bold blade
#

yes, exactly.

#

So what i said above.

#
 this.linkForm = new FormGroup({
      [NewLinkFields.destinationUrl]: new FormControl(null, {
        validators: [(control) => _linkValidationService.validUrlFormat(control)],
        updateOn: 'blur',
      }),
#

(but making it an arrow makes using it a bit nice), so u can also keep that validators array as is, but change the method to a arrow property as here. #1214948646072746034 message

tight pumice
#

Thank you, I will try to implement that

bold blade
#

TLDR: Do not pass around methods on classes as its just callbacks,as they will lose context of its this.

tight pumice
#

Alriiiight, it is working ngty 💯

#

Thanks so much!

#

One unrelated question: I want to introduce language selection on the frontend. The ErrorMessageService will return the error messages on the appropriate language. Is this approach okay? As you can see it introduces a not so common "issue"

bold blade
#

I guess u could translate on the UI level.

tight pumice
#

So, existing messages would be translated to the selected language by a 3rd party?

bold blade
#

What does a 3rd party mean in this context?

tight pumice
#

like google translate, or did you mean to actually translate it in the Angular app?

bold blade
#

How are u currently translating it ?

tight pumice
#

key: value pairs, the value being the error message. So I manually recreate the same object for different language