How to route between modules in angular2? - javascript

I am using angular2 Final for development.
I have created 3 modules.
AppModule
ProjectModule
DesignerModule
Previously I had only AppModule,In Which I had imported following RoutingModule & it worked fine.
import {NgModule} from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import {ProjectManagerComponent} from './project-manager/project-manager.component';
import {DesignerComponent} from './designer/designer.component';
const appRoutes: Routes = [
{path: '',redirectTo: 'project-manager',pathMatch: 'full'},
{ path: 'project-manager', component: ProjectManagerComponent },
{ path: 'designer/:id', component:DesignerComponent }
];
#NgModule({
imports:[RouterModule.forRoot(appRoutes)],
exports:[RouterModule]
})
export class AppRoutingModule { }
export const routingComponents=[ProjectManagerComponent,DesignerComponent]
But recently I have created separate NgModules for ProjectManager & Designer.
I have kept ProjectManagerComponent,DesignerComponent inside declarations in their respective modules.
I want to know if it is possible to route to these modules using same routing configuration or do I need to change something.
My Routing is not working anymore.
any inputs?

instead of
export const routingComponents=[ProjectManagerComponent,DesignerComponent]
you can just
export const routing = RouterModule.forRoot(appRoutes);
Since you app.module.ts already knows about ProjectManagerComponent and DesignerComponent from their respective modules. All that is left is to teach it where to go and find them.
Inside of your app.module.ts you would have
// All the other imports
import {routing} from './app.routes;'
#NgModule({
imports:[routing, /*Other Modules*/],
})

Related

Put module into component, angular

I need put a mdbModal into a component, but the component does'nt have a module.ts archive, when try this movement I get:
ERROR Error: Uncaught (in promise): Error: Export of name 'mdbModal' not found!
Error: Export of name 'mdbModal' not found!
I dont have examples in my collective project, What is the way of can import a module inside a component?
I'm relatively new on angular.
<div
mdbModal
#basicModal="mdbModal"
class="modal right modal-scroll"
tabindex="-1"
role="dialog"
aria-labelledby="myBasicModalLabel"
aria-hidden="true"
>
...
</div>
This is my parent module
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import {
ModalModule,
WavesModule,
InputsModule,
ButtonsModule,
CheckboxModule,
} from 'angular-bootstrap-md';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { SharedModule } from '../shared/shared.module';
import { NgxPaginationModule } from 'ngx-pagination';
import { PrimeDetailRoutingModule } from './prime-detail-routing.module';
import { PrimeDetailComponent } from './prime-detail.component';
#NgModule({
declarations: [PrimeDetailComponent],
imports: [
CommonModule,
PrimeDetailRoutingModule,
SharedModule,
NgxPaginationModule,
ModalModule,
WavesModule,
InputsModule,
ButtonsModule,
CheckboxModule,
FormsModule,
]
})
export class PrimeDetailModule { }
I dont have problems if I import the mdbModal inside a parent module, but yes if I need put it in the component in the absence of module.ts
prime.module.ts:
import {
ModalModule,
WavesModule,
InputsModule,
ButtonsModule,
CheckboxModule,
} from 'angular-bootstrap-md';
…
#NgModule ({
...
imports: [ModalModule.forRoot(),],
...
})
https://mdbootstrap.com/docs/b5/angular/pro/installation/
The solution for my is, you can put a Component with a Module if the component its inside of the Module Father, example:
App
MySite
Components <---
my-site.component.ts
my-site.module.ts
etc
You can put the new component in this directory <--- thats belong to MySite, you can use the next sentence in your cmd box to create:
ng generate component MySite/components/first-component --module app/MySite
After this, in the father module.ts you will see something like this:
import { FirstComponentComponent } from './components/first-component/first-component.component';
#NgModule({
declarations: [FirstComponentComponent],
})

Why Angular always redirecting to main page?

Always I trying to GET '/' it shows static-root-component (component of my main page),
but when it is '/welcome' page immediately redirecting to '/' and also loading static-root-component instead of welcome-component
Initially I wanted to redirect users to welcome page if they aren't authorized, but login status only can be checked within JavaScript. After JS got info about login status it decides to redirect using location.replace("/welcome"), but... Angular again goes to '/'
"Funny" fact: there isn't any routing problems during debug with ng serve but it always happens with ng build
I don't know what's gone wrong and there is app.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StaticRootComponent } from './static-root/static-root.component';
import { WelcomeComponent } from './welcome/welcome.component';
import { HttpClientModule } from '#angular/common/http';
import { HttpService } from './http.service';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
const appRoute: Routes = [
{ path: '', component: StaticRootComponent, pathMatch: 'full' },
{ path: 'welcome', component: WelcomeComponent }
];
#NgModule({
declarations: [
AppComponent,
StaticRootComponent,
WelcomeComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
RouterModule.forRoot(appRoute),
HttpClientModule
],
providers: [HttpService],
bootstrap: [AppComponent]
})
export class AppModule { }
I can drop any other Angular file if needed
In your code, change like below
const appRoute: Routes = [
{ path: '', component: StaticRootComponent },
{ path: 'welcome', component: WelcomeComponent },
{ path: '**', redirectTo: '' }
];
In the component file, inject this like below
import { Router } from '#angular/router';
constructor(
private router: Router
) {}
When you want do navigation use the below code instead of location.replace("/welcome")
this.router.navigate(['/welcome']);
Check the Module you trying to instantiate in the constructor of the Component linked to the Routing Path you are trying to access
In this case:
Our Component: example.component.ts
Our Module: HttpClientModule that contains HttpClient
Our Routing Path: "/example"
and make sure that Module is already existing in the app.module.ts , here is an example:
example.component.ts
import {HttpClient} from '#angular/common/http'; //child of HttpClientModule
#Component({selector: 'app-example',templateUrl: './example.component.html', styleUrls: ['./example.component.css']})
export class ExampleComponent{
constructor(private httpClient: HttpClient) { }
}
now let's see both examples of app module with and without the Module import and see the difference
app.module.ts
Without including HttpClientModule in imports array
import { AppComponent } from './app.component';
#NgModule({
declarations: [...],
imports: [BrowserModule,...],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
In this case loading the "/example" path will redirect you to the main page path which is usually "/" and that's because example.component.ts is using HttpClient (child of HttpClientModule) but not finding it in app.module.ts .
app.module.ts
Including HttpClientModule in imports array
import { AppComponent } from './app.component';
import { HttpClientModule} from '#angular/common/http'; //Import that module you willing to use
#NgModule({
declarations: [...],
imports: [BrowserModule,HttpClientModule,...], //add the module we currently using
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
In this case loading the "/example" path will work properly since we added the required module in app.module.ts.
If that's your case that would definitely fix your problem unless you have something else forcing the redirection to home page "index.html" or any other path, else if that didn't fix your problem read the following notes:
Make sure to check there are no redirections in the app-routing.module.ts routes array like this
const routes: Routes = [
{path: 'example', component: ExampleComponent},
{ path: '/example', redirectTo: '' }
];
it should only be like so
const routes: Routes = [
{path: 'example', component: ExampleComponent}
];
Also make sure there is no routing behaviour causing the redirection like #angular/router through something like this.router.navigate(['/'])
PS: SAME ISSUE COULD IMPLY IF YOU USING A SERVICE THAT'S USING A MODULE WHICH IS NOT ADDED TO MODULE IMPORTS IN app.module.ts
My project based on MEAN (Mongo, Express, Angular and NODEJS)... The last was a source of problem
#Shakthifuture, you said you want to see full code and I started answering:
"What you wanna to see else? My data and server files doesn't affec..."
and I've starting think "what if affect?": routing in whole of project works by Angular, but all new connection to the site pass NodeJS and Express, so I forgot about 404 case...
THE PROBLEM:
In server script file index.js of project's root folder a long time ago I've added code about what to do if entered path not found:
app.use(function (req, res, next) {
res.redirect('/');
// IF 404 NOT FOUND
});
and above of it something like:
app.get('/', function (req, res) {
res.sendFile(`${__dirname}/angular/index.html`)
});
// send index if path is '/'
but nothing for '/welcome', that's why redirecting happens
THE SOLUTION:
let's add the '/welcome' handler:
app.get('/welcome', function (req, res) {
res.sendFile(`${__dirname}/angular/index.html`)
});
(again index.html due to SPA)

Trigger Module Lazy Load Manually Angular 7

Official documentation has quite a lot of information about how to load angular modules lazily. [link here]
const routes: Routes = [
{
path: 'customers',
loadChildren: './customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: './orders/orders.module#OrdersModule'
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
}
];
This basically makes the module load when user visits /customers or /orders routes.
However, I can't figure out how do I load a module when from another module.
In my application I have these modules:
auth
core
events
flash messages
One route of my auth module (profile page) has to use ngrx store from events module.
My code looks like this:
import { Observable } from 'rxjs';
import { Component, OnInit } from '#angular/core';
import { Store } from '#ngrx/store';
import { AppState } from '../../app.store';
import { IUser } from '../auth.api.service';
import { selectUser } from '../store/auth.selectors';
import { IEvent } from '../../events/events.api.service';
import { selectAllEvents, selectIsLoading } from '../../events/store/events.selectors';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.scss'],
})
export class ProfileComponent implements OnInit {
isLoading$: Observable<boolean>;
events$: Observable<IEvent[]>;
user$: Observable<IUser>;
constructor(
private store: Store<AppState>,
) {
this.user$ = this.store.select(selectUser);
this.isLoading$ = this.store.select(selectIsLoading);
this.events$ = this.store.select(selectAllEvents);
}
ngOnInit() {
}
}
However, as you can expect this code does not work. Because ../../events is not loaded yet. How do I load the module manually? Something like:
constructor(
private store: Store<AppState>,
) {
this.user$ = this.store.select(selectUser);
this.loadModule('../../events/events.module.ts').then(() => {
this.isLoading$ = this.store.select(selectIsLoading);
this.events$ = this.store.select(selectAllEvents);
})
}
The Angular CLI bundler bundles up the modules based on two things:
1) If you have the modules set up for lazy loading (loadChildren), it will bundle the module up separately and provide it lazily.
2) HOWEVER, if there are any references to a lazy loaded module in any other module (by adding it to its imports array), it instead bundles the module with the referenced component.
So what should be happening is that if your events module is referenced from a component, it should be bundled with that component.
Do you have the module referenced in the imports array for the module containing the component that references it?
What error are you getting exactly?
BTW - I cover this in the "lazy loading" part of this talk: https://www.youtube.com/watch?v=LaIAHOSKHCQ&t=1120s
You need not worry about loading the ../../events. Since you have the import statement, the class/interface would be available in the module. If for some reason, you want to use features of other modules, you can add the module name in the imports array in the #NgModule declaration.

How to properly configure this dummy Angular project

I have this very basic project:
https://stackblitz.com/edit/angular-rktmgc-ktjk3n?file=index.html
This is the code on: /index.html
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="mat-app-background basic-container">
<br />
API reference for Angular Material slide-toggle<br /><br />
<select-reset-example>loading</select-reset-example>
<div style="margin-top:30px;">
<div style="color:#f00;margin-bottom:20px;">
Below is what I need to get it work like above (but it doesn't):
</div>
<mat-slide-toggle>Slide me!</mat-slide-toggle>
</div>
</div>
This is the code on: /app/select-reset-example.html
<mat-slide-toggle>Slide me!</mat-slide-toggle>
When loading the component: mat-slide-toggle through: select-reset-example it works, but when loading it directly on the index.html it doesn't.
My question is, how to configure the following /main.ts file in order to render the mat-slide-toggle directly on the index.html?
In case the scope be a problem, maybe is it possible to create a custom component which inherits from that mat-slide-toggle or MatSlideToggleModule class?
If possible, could you fork the project on stackblitz.com and give me the link
with a proper configuration?
import './polyfills';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { BrowserModule } from '#angular/platform-browser';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NgModule } from '#angular/core';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { MatSlideToggleModule } from '#angular/material';
import { SelectResetExample } from './app/select-reset-example';
import { HttpModule } from '#angular/http';
import { CdkTableModule } from '#angular/cdk/table';
#NgModule({
exports: [
MatSlideToggleModule,
]
})
export class DemoMaterialModule { }
#NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HttpModule,
DemoMaterialModule,
ReactiveFormsModule,
],
entryComponents: [SelectResetExample],
declarations: [SelectResetExample],
bootstrap: [SelectResetExample],
providers: []
})
export class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
This is the structure of the project:
Thanks!
Indeed there are several options which could be applied here.
Attempt 1
At first glance we can easily solve your problem by simply importing MatSlideToggle component and adding it to the bootstrap array:
import { MatSlideToggle } from '#angular/material';
#NgModule({
...
bootstrap: [SelectResetExample, MatSlideToggle ]
^^^^^^^^^^^^^^
cool, it was very easy!!!
})
export class AppModule { }
https://stackblitz.com/edit/angular-rktmgc-7h51hh?file=main.ts
Hmm, seems we've broken everything:).
Why?
Angular bootstraps SelectResetExample component. During this process it creates mat-slide-toggle that is part of select-reset-example.html template.
So now our html has two mat-slide-toggle tags.
And then angular bootstraps second component (MatSlideToggle) that will be applied to the first mat-slide-toggle. This way we can see that the first working slider lost text Slide me!.
Attempt 2
Let's change order of our bootstrapping components:
#NgModule({
...
bootstrap: [ MatSlideToggle, SelectResetExample ]
})
export class AppModule { }
https://stackblitz.com/edit/angular-rktmgc-mkm7ry?file=main.ts
The second slider works now but wait... We again lost the text.
The main reason of this is that angular can't process projectable nodes on bootstrapping component.
Attempt 3
Angular gives the opportunity to override bootstrapping process by writing code within ngDoBootstrap method of #NgModule. Let's try...
import { ApplicationRef, ComponentFactoryResolver, Injector, NgModuleRef } from '#angular/core';
#NgModule({
// we replaced bootstrap option with entryComponents
entryComponents: [SelectResetExample, MatSlideToggle],
})
export class AppModule {
constructor(
private resolver: ComponentFactoryResolver,
private ngModule: NgModuleRef<any>) {}
ngDoBootstrap(appRef: ApplicationRef) {
const factory = this.resolver.resolveComponentFactory(MatSlideToggle);
const target = document.querySelector('mat-slide-toggle');
const compRef = factory.create(
Injector.NULL,
[Array.from(target.childNodes)], // passing projectable nodes
target,
this.ngModule);
appRef.attachView(compRef.hostView);
appRef.bootstrap(SelectResetExample);
}
}
https://stackblitz.com/edit/angular-rktmgc-ncyebq?file=index.html
Here i am bootstrapping our components throught custom method ngDoBootstrap. And it works but...
What is this? Do I really need to know this?
I don't think so. There must be some other way out.
Attempt 4
in order not to complicate our live we should follow the design of angular framework. For that it would be better to have one root component. Let's create it:
app.component.ts
#Component({
selector: '.mat-app-background.basic-container',
templateUrl: './app.component.html',
})
export class AppComponent {
}
app.component.html
<br />
API reference for Angular Material slide-toggle<br /><br />
<select-reset-example>loading</select-reset-example>
<div style="margin-top:30px;">
<div style="color:#f00;margin-bottom:20px;">
Below is what I need to get it work like above (but it doesn't):
</div>
<mat-slide-toggle>Slide me!</mat-slide-toggle>
</div>
module
declarations: [SelectResetExample, AppComponent],
bootstrap: [AppComponent],
index.html
<div class="mat-app-background basic-container"></div>
i moved styles to external resouces
Stackblitz Example

Routing error with angular 2 and IIS [duplicate]

I'm trying to create an application with hash location strategy, but it does not add the hash to the url. For instance when I click on a button associated with { path: '/polls', name: 'Polls', component: PollsComponent } it loads the page with this url : localhost:3000/polls.
What do I have to change to get the hash location strategy?
Why do I have to set the default base url if I want to use hash location strategy?
This is the routing in the app.component.ts where all the routing is defined:
import {Component} from 'angular2/core'
import {HTTP_PROVIDERS, Http} from 'angular2/http';
import 'rxjs/Rx'; // load the full rxjs
import {ROUTER_PROVIDERS, RouteConfig , ROUTER_DIRECTIVES} from 'angular2/router';
import { ResultsComponent } from './results/results.component'
import { VotingCardsComponent } from './votingcards/votingcards.component'
import { DashBoardComponent } from './dash/dash.component'
import { PollsComponent } from './pollslist/pollslist.component'
#Component({
selector: 'my-app',
templateUrl: 'app/app.component.html',
directives: [ROUTER_DIRECTIVES, ResultsComponent, VotingCardsComponent, DashBoardComponent],
providers: [HTTP_PROVIDERS,
ROUTER_PROVIDERS]
})
#RouteConfig([
{ path: '/vote', name: 'VotePage', component: VotingCardsComponent },
{ path: '/votepoll/:id', name: 'VotePoll', component: VotingCardsComponent },
{ path: '/results', name: 'Results', component: ResultsComponent },
{ path: '/polls', name: 'Polls', component: PollsComponent },
{ path: '/', name: 'DashBoard', component: DashBoardComponent, useAsDefault: true }
])
export class AppComponent { }
And this is my main.ts where I configure the base url:
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './app.component';
//this is to avoid the href empty issue
import {provide} from 'angular2/core';
import {APP_BASE_HREF, ROUTER_PROVIDERS} from 'angular2/router';
bootstrap(AppComponent, [
//this is to avoid the href empty issue
ROUTER_PROVIDERS,
provide(LocationStrategy, { useClass: HashLocationStrategy }),
provide(APP_BASE_HREF, { useValue: '/' })
]);
You can use the option "useHash" in RouterModule.forRoot().
RouterModule.forRoot(appRoutes, {useHash: true});
https://discuss.atom.io/t/angular-2-routes-breaking-on-electron-app-refresh/28370/4
ROUTER_PROVIDERS should not be added to child components,
only to
providers: [ROUTER_PROVIDERS]
or alternatively only to
bootstrap(AppComponent, [ROUTER_PROVIDERS]);
HTTP_PROVIDERS are in my opinion also a better fit for root component or bootstrap() but it doesn't break anything to add them somewhere else.
(See also Routing error with angular 2 and IIS)
Everything worked fine with the sample code OP posted as with what is in the accepted answer. But as a minor note, the format required to changing the Hash Location Strategy in the bootstrap file as of RC.4 goes like this:
{ provide: LocationStrategy, useClass: HashLocationStrategy },
It is recommended to use the HTML 5 style (PathLocationStrategy) as location strategy in Angular
Because
It produces the clean and SEO Friendly URLs that are easier for users
to understand and remember.
You can take advantage of the server-side rendering, which will make
our application load faster, by rendering the pages in the server
first before delivering it the client.
Use Hashlocationstrtegy only if you have to support the older
browsers.
Click Here for More info

Categories