Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking: AppModules #9726

Closed
8 tasks done
tbosch opened this issue Jun 30, 2016 · 18 comments
Closed
8 tasks done

Tracking: AppModules #9726

tbosch opened this issue Jun 30, 2016 · 18 comments
Labels
effort3: weeks feature Issue that requests a new feature

Comments

@tbosch
Copy link
Contributor

tbosch commented Jun 30, 2016

AppModules introduce a way to group providers, platform directives/pipes and component factories on a higher level than components.

See this design doc for details.

This issue tracks the progress

  • main implementation
  • adjust bootstrap to use it
  • adjust bootstrap for web workers and server platform to support modules
  • create AppModules for web workers and server
  • testing support
  • define FormsModule and RouterModule
  • support for calculating precompile based on providers (needed for the router), so called ANALYZE_FOR_PRECOMPILE
  • deprecate:
    • ComponentResolver and SystemJS based implementations
      • needs (done): router supports ComponentFactoryResolver, precompile and ANALYZE_FOR_PRECOMPILE token`
      • @vsavkin
    • coreBootstrap / coreLoadAndBootstrap
      • needs (done): converting all platforms to modules)
    • providers arrays in platform-browser / platform-browser-dynamic / core/src/application_ref
      • needs (done): converting all platforms to modules)
    • old way of setting platform pipes / directives
      • needs (done): forms and router have app modules
      • console.log in CompilerConfig constructor when non empty pipes / directives are passed in
      • deprecate the symbols for PLATFORM_DIRECTIVES / PLATFORM_PIPES
        is called eagerly.
@tbosch tbosch added this to the Angular 2 Final milestone Jun 30, 2016
@tbosch tbosch added comp: core effort3: weeks feature Issue that requests a new feature labels Jun 30, 2016
tbosch added a commit to tbosch/angular that referenced this issue Jun 30, 2016
tbosch added a commit to tbosch/angular that referenced this issue Jun 30, 2016
tbosch added a commit to tbosch/angular that referenced this issue Jun 30, 2016
tbosch added a commit that referenced this issue Jun 30, 2016
@b-strauss
Copy link

b-strauss commented Jul 3, 2016

Could this be used to bundle css that should only be usable and scoped to components inside an app module? For example, commonly used flex styles.

tbosch added a commit to tbosch/angular that referenced this issue Jul 6, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  USe the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.

Related to angular#9726
@tbosch
Copy link
Contributor Author

tbosch commented Jul 6, 2016

@b-strauss Sorry, that is not planned yet.

tbosch added a commit to tbosch/angular that referenced this issue Jul 6, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` now takes a `PlatformRef` and a factory for a
  `Compiler`. Instead, use the newly added functions in
  `platform-dynamic-browser/testing` and
  `platform-server/testing` modules
  * e.g. for the browser platform, use
  ```
  setBaseTestProviders(
    testingBrowser.browserTestCompiler,
    testingBrowser.browserDynamicTestPlatform(),
    testingBrowser.BrowserDynamicTestModule);
  ```
  * e.g for the server platform, use
  ```
  setBaseTestProviders(
    testingPlatformServer.serverTestCompiler,
    testingPlatformServer.serverTestPlatform(),
    testingPlatformServer.ServerTestModule);
  ```

Related to angular#9726
tbosch added a commit to tbosch/angular that referenced this issue Jul 6, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` now takes a `PlatformRef` and a factory for a
  `Compiler`. Instead, use the newly added functions in
  `platform-dynamic-browser/testing` and
  `platform-server/testing` modules
  * e.g. for the browser platform, use
  ```
  setBaseTestProviders(
    testingBrowser.browserTestCompiler,
    testingBrowser.browserDynamicTestPlatform(),
    testingBrowser.BrowserDynamicTestModule);
  ```
  * e.g for the server platform, use
  ```
  setBaseTestProviders(
    testingPlatformServer.serverTestCompiler,
    testingPlatformServer.serverTestPlatform(),
    testingPlatformServer.ServerTestModule);
  ```

Related to angular#9726
tbosch added a commit to tbosch/angular that referenced this issue Jul 7, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` now takes a `PlatformRef` and a factory for a
  `Compiler`. Instead, use the newly added functions in
  `platform-dynamic-browser/testing` and
  `platform-server/testing` modules
  * e.g. for the browser platform, use
  ```
  setBaseTestProviders(
    testingBrowser.browserTestCompiler,
    testingBrowser.browserDynamicTestPlatform(),
    testingBrowser.BrowserDynamicTestModule);
  ```
  * e.g for the server platform, use
  ```
  setBaseTestProviders(
    testingPlatformServer.serverTestCompiler,
    testingPlatformServer.serverTestPlatform(),
    testingPlatformServer.ServerTestModule);
  ```

Related to angular#9726
tbosch added a commit to tbosch/angular that referenced this issue Jul 7, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to angular#9726
tbosch added a commit to tbosch/angular that referenced this issue Jul 7, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to angular#9726
Closes angular#9846
tbosch added a commit that referenced this issue Jul 7, 2016
Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa6).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to #9726
Closes #9846
@b-strauss
Copy link

@tbosch Is that something that would be considered? Should I create an issue for that?

@tbosch
Copy link
Contributor Author

tbosch commented Jul 7, 2016

@b-strauss Yes, please.

@tbosch
Copy link
Contributor Author

tbosch commented Jul 7, 2016

Support for adding precompile components via providers is done here: #9874

@tbosch tbosch closed this as completed Jul 7, 2016
@tbosch tbosch reopened this Jul 7, 2016
tbosch added a commit that referenced this issue Jul 7, 2016
Introduces the new `ANALYZE_FOR_PRECOMPILE` token. This token can be used to
create a virtual provider that will populate the `precompile` fields of
components and app modules based on its
`useValue`. All components that are referenced in the `useValue`
value (either directly or in a nested array or map) will be added
to the `precompile` property.

closes #9874
related to #9726
tbosch added a commit that referenced this issue Jul 8, 2016
- Introduces `CompilerFactory` which can be part of a `PlatformRef`.
- Introduces `WorkerAppModule`, `WorkerUiModule`, `ServerModule`
- Introduces `serverDynamicPlatform` for applications using runtime compilation
  on the server.
- Changes browser bootstrap for runtime and offline compilation (see below for an example).
  * introduces `bootstrapModule` and `bootstrapModuleFactory` in `@angular/core`
  * introduces new `browserDynamicPlatform` in `@angular/platform-browser-dynamic
- Changes `initTestEnvironment` (which used to be `setBaseTestProviders`) to not take a compiler factory any more (see below for an example).

BREAKING CHANGE:

## Migration from `setBaseTestProviders` to `initTestEnvironment`:

- For the browser platform:
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;

  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);
  ```

  AFTER:
  ```
  import {initTestEnvironment} from ‘@angular/core/testing’;
  import {browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;

  initTestEnvironment(
      BrowserDynamicTestModule,
      browserDynamicTestPlatform());

  ```
- For the server platform:
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;

  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);
  ```

  AFTER:
  ```
  import {initTestEnvironment} from ‘@angular/core/testing’;
  import {serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;

  initTestEnvironment(
      ServerTestModule,
      serverTestPlatform());

  ```

## Bootstrap changes
```
@appmodule({
  modules: [BrowserModule],
  precompile: [MainComponent],
  providers: […], // additional providers
  directives: […], // additional platform directives
  pipes: […] // additional platform pipes
})
class MyModule {
  constructor(appRef: ApplicationRef) {
    appRef.bootstrap(MainComponent);
  }
}

// offline compile
import {browserPlatform} from ‘@angular/platform-browser’;
import {bootstrapModuleFactory} from ‘@angular/core’;

bootstrapModuleFactory(MyModuleNgFactory, browserPlatform());

// runtime compile long form
import {browserDynamicPlatform} from ‘@angular/platform-browser-dynamic’;
import {bootstrapModule} from ‘@angular/core’;

bootstrapModule(MyModule, browserDynamicPlatform());
```

Closes #9922
Part of #9726
@tbosch tbosch closed this as completed in daa9da4 Jul 8, 2016
@playground
Copy link

@tbosch with the latest build, how can we bootstrap with custom selector?

ComponentResolver is deprecated for dynamic compilation. Use ComponentFactoryResolver together with @AppModule/@Component.precompile or ANALYZE_FOR_PRECOMPILE provider instead.

@tbosch
Copy link
Contributor Author

tbosch commented Jul 26, 2016

We don't have a nice API for this yet, sorry.

But you can do the following, please read this doc (http://g.co/ng/modules) to understand the concepts before.

@NgModule({
  imports: [BrowserModule],
  declarations: [MainComponent],
  entryComponents: [MainComponent]
})
class MainModule {
  constructor(injector: Injector, cfr: ComponentFactoryResolver, appRef: ApplicationRef) {
    const mainCompFactory = cfr.resolveComponentFactory(MainComponent);
    const compRef = mainCompFactory.create(injector, [], 'myCustomSelector');
    appRef.registerChangeDetector(compRef.changeDetectorRef);
  }
}

I.e.

  1. create a module that lists the component as an entryComponent
  2. get the ComponentFactory from the ComponentFactoryResolver
  3. create the component
  4. register it in ApplicationRef via the private API ApplicationRef.registerChangeDetector so that the component gets dirty checked

@tom-mayer
Copy link

@tbosch would it be possible to forward paremeters into the constructor? I only know the elements I want to initialize the component on at runtime (html is fetched via ajax). Probably call something like:
platformBrowserDynamic().bootstrapModule(MainModule, {selector: 'someSelector'});
when the html is in the dom and then use the 'selector' parameter in the constructor, as you described.

From what I can see right now boostrapModule does not allow to forward parameters to the module constructor, is that correct? Would you know a way to work around this until there is an API for this?

@tbosch
Copy link
Contributor Author

tbosch commented Aug 30, 2016

you can always store data in a top level variable in a module...

On Tue, Aug 30, 2016 at 9:17 AM Tom Mayer notifications@github.com wrote:

@tbosch https://github.com/tbosch would it be possible to forward
paremeters into the constructor? I only know the elements I want to
initialize the component on at runtime (html is fetched via ajax). Probably
call something like:
platformBrowserDynamic().bootstrapModule(MainModule, {selector:
'someSelector'});
when the html is in the dom and then use the 'selector' parameter in the
constructor, as you described.

From what I can see right now boostrapModule does not allow to forward
parameters to the module constructor, is that correct? Would you know a way
to work around this until there is an API for this?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#9726 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAqKf1SM5iXw03lU2zi5iV6bAdOvNKIwks5qlFZugaJpZM4JCUve
.

@tom-mayer
Copy link

tom-mayer commented Aug 31, 2016

@tbosch thanks for the pointers, after digesting your answer I noticed that I didn't even need a custom selector when using the approach you described!

For some context, I tried to instantiate multiple instances of the same root component.
http://stackoverflow.com/questions/39231943/multiple-instances-of-the-same-root-application-in-angular-2

@tom-mayer
Copy link

@tbosch Out of curiosity, you snippet worked fine in the constructor of the module. However when I put it into ngOnBootstrap of the module, it didn't start the component lifecycle (breakpoint in ngOnInit of the comonent). I also tried it as a separate method to dynamically attach components to the DOM, are there any additional steps required to start the component?

@tbosch
Copy link
Contributor Author

tbosch commented Sep 2, 2016

Not that I know of...

@tom-mayer
Copy link

Interesting, if I wrap it into a zone.run in ngDoBootstrap it works just fine. A well,... thanks for the great work so far on angular2 !

@diestrin
Copy link
Contributor

diestrin commented Sep 6, 2016

Hey @tbosch, following @playground question about custom selectors, I have created a code to dynamically bootstrap modules in my page (we have a custom set up that lazy load the components as they apear in the screen).

This code works fine and do the task, but I have a problem, when I include an NgModule in the imports of one of the bootstrapped modules, the injector doesn't recognize the services declared in the imported module. Only if I include the NgModule (the one with a service) in the root module, it gets injected correctly.

Here's a summary of the code that bootstraps with custom selector

@NgModule({
  providers: [SystemJsNgModuleLoader],
  imports: [BrowserModule]
})
class AppModule {
  ngDoBootstrap() {}
}

const modulePath = './src/test#TestModule';
const moduleSelector = '#testId';

platformBrowserDynamic()
.bootstrapModule(AppModule)
.then(appModule => {
  const ngModuleLoader = appModule.injector.get(SystemJsNgModuleLoader);
  return ngModuleLoader.loadAndCompile(modulePath)
  .then(moduleFactory => ({moduleFactory, appModule}));
})
.then(({moduleFactory, appModule}) => {
  let injector = appModule.injector;
  const ngModule = moduleFactory.create(injector);
  const app = ngModule.injector.get(ApplicationRef);

  ngModule.bootstrapFactories.forEach(comp => {
    comp.selector = moduleSelector;
    app.bootstrap(comp);
  });
});

Here's a plnkr with the example working (NgModule imported in the root module)
Here's a plnkr with the example failing because a missing provider (NgModule imported in the dynamically bootstrapped modules)
Here's a plnkr working correctly without lazy-load with custom selector

Do you have any ideas on what might be missing for the injector to recognize the services?

@tbosch
Copy link
Contributor Author

tbosch commented Sep 6, 2016

Could you create a separate issue for this? This is in general just related to module loading, and not to bootstrap of a component with a custom selector.

Your problem is that a service in a root module can not inject a service that is declared in a lazy loaded module, only the other way around. And this makes sense, as loading of modules is intended for code loading, i.e. your root module cannot refer to the service of the lazy loaded module as that code has not been loaded on bootstrap.

@diestrin
Copy link
Contributor

diestrin commented Sep 6, 2016

Moving, sorry...

@playground
Copy link

Hi @tbosch ,

Incorporating the following code snippet as you suggested with Angular 2.0.0, the components are getting bootstrapped and lazy loaded, however, they are not getting rendered as if change detection didn't kick in probably due to race condition. If we explicitly fire changeDetectorRef.detectChanges() in the console, then the components show up. Is the nice api for this available yet?

public bootstrapWithCustomSelector(moduleFactory: NgModuleFactory,
selector: string,
ngClassName: string
): void {
// Get the parent injector and create the module
const parentInjector = ReflectiveInjector.resolveAndCreate([], this.appModule.injector);
const ngModule = moduleFactory.create(parentInjector);

// Some dependencies from this module
const appRef = ngModule.injector.get(ApplicationRef);
const inj = ngModule.injector.get(Injector);
const lazyLoad = ngModule.injector.get(WuLazyLoadConfig, {component: null});

if (!lazyLoad.component) {
throw(${ngClassName} is not using the WuLazyLoadModule. This is neccesary for bootstrap the component. Check the docs.);
}

// Get the component factory and create it
const compFactory = ngModule.componentFactoryResolver
.resolveComponentFactory(lazyLoad.component);
const compRef = compFactory.create(inj, [], selector);

// Register the change detector to the app and trigger the first detection
appRef.registerChangeDetector(compRef.changeDetectorRef);
compRef.changeDetectorRef.detectChanges();
}

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
effort3: weeks feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

5 participants