Can factory provider have optional dependencies?












3














For example:



@NgModule ({
providers: [
{ provide: MyService,
useFactory: (optionalDep) => new MyService(optionalDep)
deps: [SOME_DEP]
}
})
class MyModule {}


Can useFactory have optional dependencies?










share|improve this question



























    3














    For example:



    @NgModule ({
    providers: [
    { provide: MyService,
    useFactory: (optionalDep) => new MyService(optionalDep)
    deps: [SOME_DEP]
    }
    })
    class MyModule {}


    Can useFactory have optional dependencies?










    share|improve this question

























      3












      3








      3







      For example:



      @NgModule ({
      providers: [
      { provide: MyService,
      useFactory: (optionalDep) => new MyService(optionalDep)
      deps: [SOME_DEP]
      }
      })
      class MyModule {}


      Can useFactory have optional dependencies?










      share|improve this question













      For example:



      @NgModule ({
      providers: [
      { provide: MyService,
      useFactory: (optionalDep) => new MyService(optionalDep)
      deps: [SOME_DEP]
      }
      })
      class MyModule {}


      Can useFactory have optional dependencies?







      angular typescript dependency-injection






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Sep 1 '16 at 18:54









      Krzysztof Bogdan

      456213




      456213
























          5 Answers
          5






          active

          oldest

          votes


















          7














          According to official doc, you can do the following:



          const Location = new InjectionToken('location');
          const Hash = new InjectionToken('hash');

          const injector = Injector.create([{
          provide: Hash,
          useFactory: (location: string) => `Hash for: ${location}`,
          // use a nested array to define metadata for dependencies.
          deps: [[new Optional(), Location]]
          }]);

          expect(injector.get(Hash)).toEqual('Hash for: null');


          See https://angular.io/api/core/FactoryProvider#example for more






          share|improve this answer





























            4














            I have found such a workaround:



            class OptionalDepHolder {
            constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
            }

            @NgModule ({
            providers: [
            { provide: MyService,
            useFactory: (holder) => new MyService(holder.optionalDep)
            deps: [OptionalDepHolder]
            }
            })
            class MyModule {}





            share|improve this answer





























              0














              Factory accepts a function.



              Decorators in typescript can apply on: class declaration, method, accessor, property, or parameter.



              In other words, currently you can only decorate a class and class members.




              parameter refers to the parameter of a method, not a function.




              So, since you can't decorate function and more so parameters in a function you can't set the @Optional tag.



              This a language/spec limitation that might change in the future.



              Another thing to note is that the metadata feature supported by typescript and consumed by angular using reflect-metadata is designed to work on classes. This is of course nonsense, classes are functions... but this is the general mental model.



              According to the documentation, the deps array accepts provider tokens which means you can't hint about a dependency being optional.



              It is a good idea to have support for optional dependencies in factories. You should open a GH issue with a feature request!






              share|improve this answer





























                0














                It is indeed possible to declare an optional dependency for a factory provider.



                export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
                export const myOptionalServiceParameterDefault = 42;


                Then, in your providers list, provide the default using a value provider



                @NgModule({
                providers: [
                {
                provide: MY_OPTIONAL_SERVICE_PARAMETER,
                useValue: myOptionalServiceParameterDefault
                },
                {
                provide: MyService,
                useFactory: (optionalParam) => new MyService(optionalParam)
                deps: [MY_OPTIONAL_SERVICE_PARAMETER]
                }
                })
                export class Module {}


                The service will use the provided default value of the parameter (which could be undefined), unless the consumer overrides the value later in the list of providers.



                The HttpModule from @angular/http uses this pattern to provide the optional dependency RequestOptions to its services.






                share|improve this answer































                  0














                  so I've been trying to solve it. Check this:



                  @NgModule ({
                  providers: [
                  { provide: MyService,
                  useFactory: (optionalDep) => new MyService(optionalDep)
                  deps: [[new Optional(), new Inject(SOME_DEP)]]
                  }
                  })
                  class MyModule {}





                  share|improve this answer





















                    Your Answer






                    StackExchange.ifUsing("editor", function () {
                    StackExchange.using("externalEditor", function () {
                    StackExchange.using("snippets", function () {
                    StackExchange.snippets.init();
                    });
                    });
                    }, "code-snippets");

                    StackExchange.ready(function() {
                    var channelOptions = {
                    tags: "".split(" "),
                    id: "1"
                    };
                    initTagRenderer("".split(" "), "".split(" "), channelOptions);

                    StackExchange.using("externalEditor", function() {
                    // Have to fire editor after snippets, if snippets enabled
                    if (StackExchange.settings.snippets.snippetsEnabled) {
                    StackExchange.using("snippets", function() {
                    createEditor();
                    });
                    }
                    else {
                    createEditor();
                    }
                    });

                    function createEditor() {
                    StackExchange.prepareEditor({
                    heartbeatType: 'answer',
                    autoActivateHeartbeat: false,
                    convertImagesToLinks: true,
                    noModals: true,
                    showLowRepImageUploadWarning: true,
                    reputationToPostImages: 10,
                    bindNavPrevention: true,
                    postfix: "",
                    imageUploader: {
                    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                    allowUrls: true
                    },
                    onDemand: true,
                    discardSelector: ".discard-answer"
                    ,immediatelyShowMarkdownHelp:true
                    });


                    }
                    });














                    draft saved

                    draft discarded


















                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39278930%2fcan-factory-provider-have-optional-dependencies%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown

























                    5 Answers
                    5






                    active

                    oldest

                    votes








                    5 Answers
                    5






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    7














                    According to official doc, you can do the following:



                    const Location = new InjectionToken('location');
                    const Hash = new InjectionToken('hash');

                    const injector = Injector.create([{
                    provide: Hash,
                    useFactory: (location: string) => `Hash for: ${location}`,
                    // use a nested array to define metadata for dependencies.
                    deps: [[new Optional(), Location]]
                    }]);

                    expect(injector.get(Hash)).toEqual('Hash for: null');


                    See https://angular.io/api/core/FactoryProvider#example for more






                    share|improve this answer


























                      7














                      According to official doc, you can do the following:



                      const Location = new InjectionToken('location');
                      const Hash = new InjectionToken('hash');

                      const injector = Injector.create([{
                      provide: Hash,
                      useFactory: (location: string) => `Hash for: ${location}`,
                      // use a nested array to define metadata for dependencies.
                      deps: [[new Optional(), Location]]
                      }]);

                      expect(injector.get(Hash)).toEqual('Hash for: null');


                      See https://angular.io/api/core/FactoryProvider#example for more






                      share|improve this answer
























                        7












                        7








                        7






                        According to official doc, you can do the following:



                        const Location = new InjectionToken('location');
                        const Hash = new InjectionToken('hash');

                        const injector = Injector.create([{
                        provide: Hash,
                        useFactory: (location: string) => `Hash for: ${location}`,
                        // use a nested array to define metadata for dependencies.
                        deps: [[new Optional(), Location]]
                        }]);

                        expect(injector.get(Hash)).toEqual('Hash for: null');


                        See https://angular.io/api/core/FactoryProvider#example for more






                        share|improve this answer












                        According to official doc, you can do the following:



                        const Location = new InjectionToken('location');
                        const Hash = new InjectionToken('hash');

                        const injector = Injector.create([{
                        provide: Hash,
                        useFactory: (location: string) => `Hash for: ${location}`,
                        // use a nested array to define metadata for dependencies.
                        deps: [[new Optional(), Location]]
                        }]);

                        expect(injector.get(Hash)).toEqual('Hash for: null');


                        See https://angular.io/api/core/FactoryProvider#example for more







                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Feb 1 at 16:38









                        maxime1992

                        10.5k43473




                        10.5k43473

























                            4














                            I have found such a workaround:



                            class OptionalDepHolder {
                            constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
                            }

                            @NgModule ({
                            providers: [
                            { provide: MyService,
                            useFactory: (holder) => new MyService(holder.optionalDep)
                            deps: [OptionalDepHolder]
                            }
                            })
                            class MyModule {}





                            share|improve this answer


























                              4














                              I have found such a workaround:



                              class OptionalDepHolder {
                              constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
                              }

                              @NgModule ({
                              providers: [
                              { provide: MyService,
                              useFactory: (holder) => new MyService(holder.optionalDep)
                              deps: [OptionalDepHolder]
                              }
                              })
                              class MyModule {}





                              share|improve this answer
























                                4












                                4








                                4






                                I have found such a workaround:



                                class OptionalDepHolder {
                                constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
                                }

                                @NgModule ({
                                providers: [
                                { provide: MyService,
                                useFactory: (holder) => new MyService(holder.optionalDep)
                                deps: [OptionalDepHolder]
                                }
                                })
                                class MyModule {}





                                share|improve this answer












                                I have found such a workaround:



                                class OptionalDepHolder {
                                constructor(@Optional() @Inject(SOME_DEP) public optionalDep) {}
                                }

                                @NgModule ({
                                providers: [
                                { provide: MyService,
                                useFactory: (holder) => new MyService(holder.optionalDep)
                                deps: [OptionalDepHolder]
                                }
                                })
                                class MyModule {}






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Sep 1 '16 at 21:41









                                Krzysztof Bogdan

                                456213




                                456213























                                    0














                                    Factory accepts a function.



                                    Decorators in typescript can apply on: class declaration, method, accessor, property, or parameter.



                                    In other words, currently you can only decorate a class and class members.




                                    parameter refers to the parameter of a method, not a function.




                                    So, since you can't decorate function and more so parameters in a function you can't set the @Optional tag.



                                    This a language/spec limitation that might change in the future.



                                    Another thing to note is that the metadata feature supported by typescript and consumed by angular using reflect-metadata is designed to work on classes. This is of course nonsense, classes are functions... but this is the general mental model.



                                    According to the documentation, the deps array accepts provider tokens which means you can't hint about a dependency being optional.



                                    It is a good idea to have support for optional dependencies in factories. You should open a GH issue with a feature request!






                                    share|improve this answer


























                                      0














                                      Factory accepts a function.



                                      Decorators in typescript can apply on: class declaration, method, accessor, property, or parameter.



                                      In other words, currently you can only decorate a class and class members.




                                      parameter refers to the parameter of a method, not a function.




                                      So, since you can't decorate function and more so parameters in a function you can't set the @Optional tag.



                                      This a language/spec limitation that might change in the future.



                                      Another thing to note is that the metadata feature supported by typescript and consumed by angular using reflect-metadata is designed to work on classes. This is of course nonsense, classes are functions... but this is the general mental model.



                                      According to the documentation, the deps array accepts provider tokens which means you can't hint about a dependency being optional.



                                      It is a good idea to have support for optional dependencies in factories. You should open a GH issue with a feature request!






                                      share|improve this answer
























                                        0












                                        0








                                        0






                                        Factory accepts a function.



                                        Decorators in typescript can apply on: class declaration, method, accessor, property, or parameter.



                                        In other words, currently you can only decorate a class and class members.




                                        parameter refers to the parameter of a method, not a function.




                                        So, since you can't decorate function and more so parameters in a function you can't set the @Optional tag.



                                        This a language/spec limitation that might change in the future.



                                        Another thing to note is that the metadata feature supported by typescript and consumed by angular using reflect-metadata is designed to work on classes. This is of course nonsense, classes are functions... but this is the general mental model.



                                        According to the documentation, the deps array accepts provider tokens which means you can't hint about a dependency being optional.



                                        It is a good idea to have support for optional dependencies in factories. You should open a GH issue with a feature request!






                                        share|improve this answer












                                        Factory accepts a function.



                                        Decorators in typescript can apply on: class declaration, method, accessor, property, or parameter.



                                        In other words, currently you can only decorate a class and class members.




                                        parameter refers to the parameter of a method, not a function.




                                        So, since you can't decorate function and more so parameters in a function you can't set the @Optional tag.



                                        This a language/spec limitation that might change in the future.



                                        Another thing to note is that the metadata feature supported by typescript and consumed by angular using reflect-metadata is designed to work on classes. This is of course nonsense, classes are functions... but this is the general mental model.



                                        According to the documentation, the deps array accepts provider tokens which means you can't hint about a dependency being optional.



                                        It is a good idea to have support for optional dependencies in factories. You should open a GH issue with a feature request!







                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Sep 1 '16 at 20:59









                                        Shlomi Assaf

                                        1,272813




                                        1,272813























                                            0














                                            It is indeed possible to declare an optional dependency for a factory provider.



                                            export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
                                            export const myOptionalServiceParameterDefault = 42;


                                            Then, in your providers list, provide the default using a value provider



                                            @NgModule({
                                            providers: [
                                            {
                                            provide: MY_OPTIONAL_SERVICE_PARAMETER,
                                            useValue: myOptionalServiceParameterDefault
                                            },
                                            {
                                            provide: MyService,
                                            useFactory: (optionalParam) => new MyService(optionalParam)
                                            deps: [MY_OPTIONAL_SERVICE_PARAMETER]
                                            }
                                            })
                                            export class Module {}


                                            The service will use the provided default value of the parameter (which could be undefined), unless the consumer overrides the value later in the list of providers.



                                            The HttpModule from @angular/http uses this pattern to provide the optional dependency RequestOptions to its services.






                                            share|improve this answer




























                                              0














                                              It is indeed possible to declare an optional dependency for a factory provider.



                                              export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
                                              export const myOptionalServiceParameterDefault = 42;


                                              Then, in your providers list, provide the default using a value provider



                                              @NgModule({
                                              providers: [
                                              {
                                              provide: MY_OPTIONAL_SERVICE_PARAMETER,
                                              useValue: myOptionalServiceParameterDefault
                                              },
                                              {
                                              provide: MyService,
                                              useFactory: (optionalParam) => new MyService(optionalParam)
                                              deps: [MY_OPTIONAL_SERVICE_PARAMETER]
                                              }
                                              })
                                              export class Module {}


                                              The service will use the provided default value of the parameter (which could be undefined), unless the consumer overrides the value later in the list of providers.



                                              The HttpModule from @angular/http uses this pattern to provide the optional dependency RequestOptions to its services.






                                              share|improve this answer


























                                                0












                                                0








                                                0






                                                It is indeed possible to declare an optional dependency for a factory provider.



                                                export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
                                                export const myOptionalServiceParameterDefault = 42;


                                                Then, in your providers list, provide the default using a value provider



                                                @NgModule({
                                                providers: [
                                                {
                                                provide: MY_OPTIONAL_SERVICE_PARAMETER,
                                                useValue: myOptionalServiceParameterDefault
                                                },
                                                {
                                                provide: MyService,
                                                useFactory: (optionalParam) => new MyService(optionalParam)
                                                deps: [MY_OPTIONAL_SERVICE_PARAMETER]
                                                }
                                                })
                                                export class Module {}


                                                The service will use the provided default value of the parameter (which could be undefined), unless the consumer overrides the value later in the list of providers.



                                                The HttpModule from @angular/http uses this pattern to provide the optional dependency RequestOptions to its services.






                                                share|improve this answer














                                                It is indeed possible to declare an optional dependency for a factory provider.



                                                export const MY_OPTIONAL_SERVICE_PARAMETER = new OpaqueToken('my_optional_service_parameter');
                                                export const myOptionalServiceParameterDefault = 42;


                                                Then, in your providers list, provide the default using a value provider



                                                @NgModule({
                                                providers: [
                                                {
                                                provide: MY_OPTIONAL_SERVICE_PARAMETER,
                                                useValue: myOptionalServiceParameterDefault
                                                },
                                                {
                                                provide: MyService,
                                                useFactory: (optionalParam) => new MyService(optionalParam)
                                                deps: [MY_OPTIONAL_SERVICE_PARAMETER]
                                                }
                                                })
                                                export class Module {}


                                                The service will use the provided default value of the parameter (which could be undefined), unless the consumer overrides the value later in the list of providers.



                                                The HttpModule from @angular/http uses this pattern to provide the optional dependency RequestOptions to its services.







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Nov 18 '16 at 12:07

























                                                answered Nov 17 '16 at 23:55









                                                ovangle

                                                5641620




                                                5641620























                                                    0














                                                    so I've been trying to solve it. Check this:



                                                    @NgModule ({
                                                    providers: [
                                                    { provide: MyService,
                                                    useFactory: (optionalDep) => new MyService(optionalDep)
                                                    deps: [[new Optional(), new Inject(SOME_DEP)]]
                                                    }
                                                    })
                                                    class MyModule {}





                                                    share|improve this answer


























                                                      0














                                                      so I've been trying to solve it. Check this:



                                                      @NgModule ({
                                                      providers: [
                                                      { provide: MyService,
                                                      useFactory: (optionalDep) => new MyService(optionalDep)
                                                      deps: [[new Optional(), new Inject(SOME_DEP)]]
                                                      }
                                                      })
                                                      class MyModule {}





                                                      share|improve this answer
























                                                        0












                                                        0








                                                        0






                                                        so I've been trying to solve it. Check this:



                                                        @NgModule ({
                                                        providers: [
                                                        { provide: MyService,
                                                        useFactory: (optionalDep) => new MyService(optionalDep)
                                                        deps: [[new Optional(), new Inject(SOME_DEP)]]
                                                        }
                                                        })
                                                        class MyModule {}





                                                        share|improve this answer












                                                        so I've been trying to solve it. Check this:



                                                        @NgModule ({
                                                        providers: [
                                                        { provide: MyService,
                                                        useFactory: (optionalDep) => new MyService(optionalDep)
                                                        deps: [[new Optional(), new Inject(SOME_DEP)]]
                                                        }
                                                        })
                                                        class MyModule {}






                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Nov 11 at 17:25









                                                        Jan Kremeň

                                                        1




                                                        1






























                                                            draft saved

                                                            draft discarded




















































                                                            Thanks for contributing an answer to Stack Overflow!


                                                            • Please be sure to answer the question. Provide details and share your research!

                                                            But avoid



                                                            • Asking for help, clarification, or responding to other answers.

                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                            To learn more, see our tips on writing great answers.





                                                            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                                                            Please pay close attention to the following guidance:


                                                            • Please be sure to answer the question. Provide details and share your research!

                                                            But avoid



                                                            • Asking for help, clarification, or responding to other answers.

                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                            To learn more, see our tips on writing great answers.




                                                            draft saved


                                                            draft discarded














                                                            StackExchange.ready(
                                                            function () {
                                                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f39278930%2fcan-factory-provider-have-optional-dependencies%23new-answer', 'question_page');
                                                            }
                                                            );

                                                            Post as a guest















                                                            Required, but never shown





















































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown

































                                                            Required, but never shown














                                                            Required, but never shown












                                                            Required, but never shown







                                                            Required, but never shown







                                                            這個網誌中的熱門文章

                                                            Xamarin.form Move up view when keyboard appear

                                                            Post-Redirect-Get with Spring WebFlux and Thymeleaf

                                                            Anylogic : not able to use stopDelay()