I am working on an angular application that has 3 modules, root module auth module, and dashboard module. In my root module routing file I load auth and dashboard module using load children approach however dashboard module almost always load first when the user is logged in so I don't want to lazy load my dashboard module.
I search a day and looking for a solution I looked in the angular document to find a way to normal load a module however the only things I found was Angular switch from lazyLoading to 'normal' loading question which the answer doesn't work in aot compile production mode and I got this error
Error: Runtime compiler is not loaded
So how can I normal load my dashboard module in angular?
If you dont want lazy loading, remove the route corresponding to the load children from the root routing module. Instead place the import statement of the feature module(in your case auth and dashboard module) before the root routing module import. Angular will compile your feature module since it is in the imports array(not lazy load). Since the order matters, the routes in the feature module will be hit first rendering the feature modules' components.
I suggest you to read the documentation for routing and navigation from the official docs
Related
I have built an application with Angular 12.
I have a JS module called dynamic_module.js which is not available at build time which I want to import and use in the app. However, dynamic_module.js uses rxjs and other imports - all of which are already used in the Angular application and so included in the built webpack. dynamic_module is not an Angular / webpack artifact or anything complicated - it is a simple JavaScript file located on the same server but not available at build time .
When I try to import "dynamic_module.js" using the import(<path_to_dynamic_module.js> ) function - (I'm assuming this method is hi-jacked by webpack) I get an error:
"Error: Cannot find module '<path_to_dynamic_module.js>' ".
I expected this because the dynamic_module.js is not available when the app was built.
So, I tried the method of inserting a <script> element into the header -
e.g. <script type="module" src="<url_of_dynamic_module.js>"></script>
this loads the module but reports the error :
Failed to resolve module specifier "rxjs". Relative
references must start with either "/", "./", or "../".
I also tried this without the import of rxjs in the module, and it works ok.
And if I try using SystemJS with the babel transpiler and try to import the dynamic_module.js, I get an error when System JS tries to load the rxjs module it goes to http.
Error: Fetch error: 404 Not Found Instantiating
http://localhost:4400/rxjs
This also works when the import is removed from dynamic_module.js.
My question is : Can modules dynamically loaded with SystemJS (or any other method) import other modules that are already loaded by webpack - without duplication or reloading via http?
If this is not possible, I could make all the necessary module files available via http for SystemJS to load (I have done this with the 'babel' transpiler modules for SystemJS) . Would that cause two copies of the modules (ie. rxjs in this example) to be loaded into the browser - could this be a serious problem (space/performance/clashes ...)?
Here is a very simple example of the module - this can load by any method if the import is removed, but fails in if the import is included.
dynamic_module.js
import { Observable} from 'rxjs';
export class MyClass{
hello( msg ) {
console.log('[MODULE] Hello World');
console.log(msg);
}
}
Thanks for any advice!
Ok, after some research I have solved my problem:
Let me describe concisely what the issue I had was:
I was trying to import a module (dynamic_module.js) into an Angular
application at run time,
that module had a dependency on a module that was already bundled in
the Angular webpack (rxjs)
I used SystemJS to import my dynamic module
SystemJS tried to resolve my dynamic_module's dependencies by
reloading modules from the server.
I felt that this was unnecessary because the modules were already present in the client application - and anyway, the http requests failed because the dependencies were not to be found where it was looking for them.
The solution is to let SystemJS know in advance that the dependencies are already available. This is done using the SystemJS.set() method: for example in my case the key steps were:
import * as rxjs from "rxjs";
SystemJS.set('rxjs', SystemJS.newModule(rxjs));
SystemJS.import( <url_of_module> ).then( module=>.....});
How can I use a module in another module in angular 8? I would like create an application that use a modules in another module. is it possible? if yes how can I route from a link to this modules?
I build a menu module and inside that some components as menus. any menu refer to a new area that I want be a module. how can I do this?
the structure is:
menu(module)
-first menu(component)
an area(module)
some components
...
-second menu(component)
...
Normally you will need to lazy load module
So what you need to do is
Create a desire module you want to have in your app and include component you need
Then add default route for that module
Lazy load that module in your main app.routing.ts
Add routeroutlet in your view to navigate to that route moudule
I have a hybrid angular app and unit testing with Karma-Jasmine but we hit a small problem. I have a factory and component that is downgraded as an AngularJS app with:
angular
.module('app.admin.branding')
.factory('brandingFactory', downgradeInjectable(BrandingFactory));
angular
.module('app.admin.branding')
.directive('BrandNameComponent', downgradeComponent({
component: BrandNameComponent
}));
but it returns a Module 'app.admin.branding' is not available! upon running ng test
so the solution was adding brackets.
angular
.module('app.admin.branding', [])
for both the component and factory. It works and the unit tests runs but when running on the browser and navigates to a page where the component is used an unknown error occurs and redirected to the main page.
So we just removed the brackets for both classes as it affected our production app. How do we fix our unit test error Module 'app.admin.branding' is not available or is there any workaround with the brackets approach so that it won't redirect?
Short answer;
Not quite sure about your setup, there might be a number of problems. The first thing to try is to use angular.mock.module, like so;
beforeEach(() => TestBed.configureTestingModule({}));
beforeEach(angular.mock.module('app.admin.branding'));
See documentation here
Hopefully this is all that you need
Longer answer;
You may also have a problem with your "import chain".
As you have noticed the angularJS module gets created when you execute angular.module('app.admin.branding', []). When you append services, directives etc to this module you refer to it without the brackets.
When creating a hybrid app you need to be careful when creating the "import chain", i.e. the chain of import statements that link your app together.
Below is the structure of a working angular hybrid created with angular-cli.
The app-ajs folder contains the angularJS app and each folder below this directory contains an index.ts file that imports all directives, services etc inside the folder.
The first index.ts file in our application looks like this;
// Vendor dependencies;
import './../../node_modules/adal-angular/dist/adal-angular.min';
import './../../node_modules/angular-cookies/angular-cookies.min';
// ...etc.
// App dependencies...
import './app.module';
import './appDependencies.module';
import './subfolder1'; // In reality this is an app area, just to show the idea!
import './subfolder2';
And an index.ts below a sub folder may look something like this;
import './some.module';
import './some.service';
import './some.directive';
In this case there would be a file named some.module.ts inside that folder that would contain the call to register to module (i.e. angular.module('some.module', []))
Creating this import chain is a bit tedious, but once you have it in place you can use it from both your main.ts and test.ts by importing it like this:
import "./app-ajs";
This makes sure you run the same code in production as in your tests.
Hope this helps.
Starting with Angular 8, there is createAngularJSTestingModule. See https://angular.io/api/upgrade/static/testing/createAngularJSTestingModule for an example.
I'm using Angular2 in my project and I have several modules.
I have base module which is called BaseModule
And have for example two (or more) extra modules - FirstModule and SecondModule.
Each module has his own routing. BaseModule has basic routes for system,
FirstModule and SecondModule has his own separated routes.
BUT
I want to create routes like
/user/10/profile
Where ProfileComponent for user contains into FirstModule
Another examples
/user/10/stories
Where StoriesComponent for user contains into FirstModule
/user/10/news
Where NewsComponent for user contains into SecondModule!!!!
But Angular Router allow only routes like:
/firstmodule/......
/secondmodule/......
So, they should be grouped by module.
I want to do it with modules because I want to have async(lazy) loaded parts of my application.
As I know Angular disallow variants when we async(lazy) load components.
Anybody have ideas how I can create what I want?
For routes in root module define your roots as RouterModule.forRoot(['']) and for routes in the other modules use RouterModule.forChild(['']). Since your child modules will be in the imports of the parent this will route properly.
I'm inspecting this Webpack demo project https://github.com/Foxandxss/GermanWords-ng1-webpack. This project contains in several files this line (features/home/index, features/login/index):
import angular from 'angular';
I don't understand - if 'angular' library will be included several times in result js file because this library exists in several source files? I've looked at webpack config file, but can't understand. Please, can you clear this questions?
It's just to be sure that angular will be available for every module. Imagine you use a feature to be a new standalone site, you will have already the code ready. Always think like every feature is a standalone (handle routes, dependencies, controllers, views etc.).
Webpack will handle the dependencies and inject only once angular, dont worry. Like #thsorens says in comments : "All dependencies in your files needs to be imported where it is used."
Oh and for furthermore, i've found this yeoman generator base on Foxandxss work : https://github.com/Aleksion/generator-angular-webpack-babel
Have fun.