Home > Mobile >  properly understanding inject in angular14 - inject() must be called from an injection context
properly understanding inject in angular14 - inject() must be called from an injection context

Time:06-06

I'm trying to learn the changes in angular 14, especially the inject() feature where i'm able to inject modules to functions and i don't need to create special services for that.. but i think i got something wrong.

I'm trying to create some static functions to send snack messages using the package ngx-toastr, but this package is not relevant to my question. how do I properly implement functions that show snack messages while injecting to them the required modules that they need to operate.

this is my messages.ts file:

import {inject} from '@angular/core';
import {ToastrService} from 'ngx-toastr';


export const snackMsgSuccess = (msg: string, title?: string) => {
  const toaster = inject(ToastrService);
  toaster.success(msg, title, {
    easeTime: 1000
  });
};


export const snackMsgInfo = (msg: string, title?: string) => {
  const toaster = inject(ToastrService);
  toaster.info(msg, title, {
    easeTime: 1000
  });
};

export const snackMsgWarn = (msg: string, title?: string) => {
  const toaster = inject(ToastrService);
  toaster.warning(msg, title, {
    easeTime: 1000
  });
};


export const snackMsgError = (msg: string, title?: string) => {
  const toaster = inject(ToastrService);
  toaster.error(msg, title, {
    easeTime: 1000
  });
};

and I got the following error:

Error: Uncaught (in promise): Error: NG0203: inject() must be called from an injection context (a constructor, a factory function or a field initializer)

well... i had a problem before when i tried to have a supporting function to get route params:

export const routeParam$ = (key: string) => {
  const activatedRoute = inject(ActivatedRoute);

  return activatedRoute.params.pipe(
    pluck(key),
    filter(r => r !== null),
    distinctUntilChanged()
  );
};

and i was only able to use as an field initializer in a component with task: Observable<string> = routeParam$('task');

well the error message is very clear... but still.. i'm new to angular14 and i thought that inject would allow me to do that. it's not that useful for me otherwise.

for now I moved it as a service..

import {Injectable} from '@angular/core';
import {ToastrService} from 'ngx-toastr';

@Injectable({
  providedIn: 'root'
})
export class MsgService {

  constructor(private toaster: ToastrService) {
  }

  public snackMsgSuccess = (msg: string, title?: string) => {
    this.toaster.success(msg, title, {
      easeTime: 1000
    });
  };


  public snackMsgInfo = (msg: string, title?: string) => {
    this.toaster.info(msg, title, {
      easeTime: 1000
    });
  };

  public snackMsgWarn = (msg: string, title?: string) => {
    this.toaster.warning(msg, title, {
      easeTime: 1000
    });
  };


  public snackMsgError = (msg: string, title?: string) => {
    this.toaster.error(msg, title, {
      easeTime: 1000
    });
  };
}

but is this the only way to implement it ? even in angular14 ?

CodePudding user response:

As mentioned in the Answer, It can be only initialised during instantiation of a dependency by the DI system. You can workaround this by creating inner function.

export const snackMsgSuccess = () => {
  const toaster = inject(ToastrService);
  return (msg: string,title?: string)=>{
    toaster.success(msg, title, {
      easeTime: 1000
    });
  }
};

component.ts

snackMsgSuccess = snackMsgSuccess();


ngOnInit(){
   this.snackMsgSuccess('Success','Test');
}
  • Related