在Angular14 -Inject()中正确理解注入必须从注射环境中调用

发布于 2025-02-04 11:13:23 字数 2482 浏览 6 评论 0原文

我正在尝试学习Angular 14中的更改,尤其是Inject()功能,我能够将模块注入功能,而我不需要为此创建特殊服务。我想我错了。

我正在尝试创建一些静态功能,以使用软件包ngx-toastr发送零食消息,但是此软件包与我的问题无关。我如何正确地实现显示零食消息的功能,同时向它们注入他们需要操作的所需模块。

这是我的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
  });
};

我有以下错误:

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

嗯...我在尝试具有支持功能以获取路线参数之前遇到了问题:

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

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

而且我只能能够用作具有任务的组件中的字段初始化器:可观察< string> = RouteParam $('task');

错误消息非常清楚...但是仍然..我是Angular14的新手,我认为注入可以让我这样做。否则对我来说并不有用。

目前,我将其作为服务移动。

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
    });
  };
}

但是,这是实施它的唯一方法吗?即使在Angular14中?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

怎樣才叫好 2025-02-11 11:13:24

由于Angular 14.1,您可以使用 runinContext

简单示例:简单示例:

class Foo {
    constructor(private injector: EnvironmentInjector) {
        setTimeout(() => {
            // can't inject()

            this.injector.runInContext(() => {
                inject(MyService) // fine
            });
        }, 1000);
    }
}

Since Angular 14.1 you can use the runInContext :

Simple example:

class Foo {
    constructor(private injector: EnvironmentInjector) {
        setTimeout(() => {
            // can't inject()

            this.injector.runInContext(() => {
                inject(MyService) // fine
            });
        }, 1000);
    }
}
暮色兮凉城 2025-02-11 11:13:24

V16+使用 runinInIndoctionContext

injector = inject(EnvironmentInjector);

constructor(private injector: EnvironmentInjector)

runInInjectionContext(this.injector, snackMsgSuccess);

In the v16+ use runInInjectionContext

injector = inject(EnvironmentInjector);

or

constructor(private injector: EnvironmentInjector)

and then

runInInjectionContext(this.injector, snackMsgSuccess);
雨后咖啡店 2025-02-11 11:13:24

您可能会收到此错误的原因之一是因为您依赖于与主软件包不同版本的库,并且您正在将该库的模块导入到角度模块中。

您应该能够通过查看node_modules/some_library/node_modules来确定这一点,并查看那里是否存在@angular库。

这个答案是解决方案。适当的解决方案是确保您的主包和您所依赖的库是使用@Angular软件包的相同版本。一种方法是确保您拥有相同的主要版本,并将^用作@Angular packages in package.json < /代码>。

One reason why you may receive this error is because you are dependent on a library that depends on a different version of Angular than your main package does, and you are importing that library's module into your Angular module.

You should be able to determine this by looking at node_modules/some_library/node_modules, and seeing if @angular libraries are present there.

This answer is a workaround for that. The proper solution is to make sure your main package and the library you depend on are using the same versions of @angular packages. One way to do this is to make sure you have the same major version, and use ^ as your semver prefix for @angular packages in your package.json.

负佳期 2025-02-11 11:13:24

如果您使用Angular 17.2和库17.3,则有关版本的问题。绝对您可以获得此错误

This Problem about Version if you use angular 17.2 and your library 17.3. Absolutly you can get this error

二智少女 2025-02-11 11:13:23

如答案中所述,只能在DI系统对依赖性实例化期间初始化。您可以通过创建高阶功能来解决此问题。

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');
}

更新本版本功能中的Angular 14.1

可以使用RunIncontext API在功能主体内部使用。

有关更多信息

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 higher order 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');
}

Update Angular 14.1

In this version inject function can be used inside function body using runInContext API.

For More Info

述情 2025-02-11 11:13:23

对于使用NX和Angular 15的Angular项目,我遇到了同样的问题,而无需违反此规则。我已经解决了它,将以下行添加到compileroptions.paths 在tsconfig.base.json文件中:

“@angular/*”:[“ node_modules/@anguarl/@anguarl/*”]

I had the same issue for one of my Angular projects using Nx and Angular 15 without breaking this rule. I got it solved adding the following line to compilerOptions.paths in the tsconfig.base.json file:

"@angular/*": ["node_modules/@angular/*"]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文