I am having problem with angular 12 sub routes. I can navigate to the sub routes just fine but when I refresh the page I lose context. I am running it locally on the localhost:4200
here is the image of what I am getting in network tab and on the screen when I refresh
enter image description here
here is a link for source code: https://github.com/Stanmozolevskiy/Portfolio
Here is routing component:
import { SinglePortfolioComponent } from './portfolio/single-portfolio/single-portfolio.component';
import { HomeComponent } from './home/home.component';
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { ContactComponent } from './contact/contact.component';
import { AboutComponent } from './about/about.component';
import { PortfolioComponent } from './portfolio/portfolio.component';
const routes: Routes = [
{path: '', component: HomeComponent},
{path: 'contact', component: ContactComponent},
{path: 'about', component: AboutComponent},
{path: 'about/portfolio', component: AboutComponent},
{path: 'portfolio', component: PortfolioComponent},
{path: 'portfolio/:query', component: SinglePortfolioComponent},
];
#NgModule({
imports: [RouterModule.forRoot(routes, {scrollPositionRestoration: 'enabled'})],
exports: [RouterModule]
})
export class AppRoutingModule { }
Here is app module:
import { AngularFireModule } from '#angular/fire';
import { AngularFireFunctionsModule } from '#angular/fire/functions';
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { FontAwesomeModule } from '#fortawesome/angular-fontawesome';
import { ContactComponent } from './contact/contact.component';
import { ReactiveFormsModule } from '#angular/forms';
import { AboutComponent } from './about/about.component';
import { GetintouchComponent } from './getintouch/getintouch.component';
import { PortfolioComponent } from './portfolio/portfolio.component';
import { SinglePortfolioComponent } from './portfolio/single-portfolio/single-portfolio.component';
import { HeaderComponent } from './common/header/header.component';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { AsideComponent } from './common/aside/aside.component';
import { ParagraphComponent } from './common/paragraph/paragraph.component';
#NgModule({
declarations: [
AppComponent,
HomeComponent,
ContactComponent,
AboutComponent,
GetintouchComponent,
PortfolioComponent,
SinglePortfolioComponent,
HeaderComponent,
AsideComponent,
ParagraphComponent
],
imports: [
AppRoutingModule,
BrowserModule,
FontAwesomeModule,
ReactiveFormsModule ,
AngularFireFunctionsModule,
NgbModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
I will be happy to try any suggestions, thank you in advance!
Solution to this problem:
Change your webserver configurations to match your location strategy or use HashLocationStrategy as follow: imports: [RouterModule.forRoot(appRoutes, {scrollPositionRestoration: 'enabled', useHash: true})]
And please change all href attributes over your code base to routerLink directive as follow:
<a routerLink="/portfolio" class="btn btn-lg edit_hover_class custom-btn">
<fa-icon [icon]="faBriefcase"></fa-icon> My portfolio
</a>
I assume you're talking about the index.html fallback that doesn't work on the production like it works locally while in development.
You can fix your issue by looking at the docs here https://angular.io/guide/deployment#routed-apps-must-fallback-to-indexhtml.
Just know what is your online server and do the solution specific for it.
Related
I'm new to angular and I was wondering how I could load a different home.component.html file from a method that's inside books.component.ts.
This is my books.component.ts file.
import { Component, OnInit } from '#angular/core';
import {BooksService} from '../books.service';
import {NgForm} from '#angular/forms';
import { Router } from '#angular/router';
#Component({
selector: 'app-books',
templateUrl: './books.component.html',
styleUrls: ['./books.component.css']
})
export class BooksComponent {
constructor(private httpService: BooksService, private router:Router) {
}
status : any;
onSubmit(f: NgForm) {
console.log("AM I HERE AT LEAST");
this.httpService.checkLoginCred(f.value).subscribe(
data => {
// console.log(Object.values(data)[0]);
this.status = Object.values(data)[0];
if(this.status === "Successful"){
var path = "../home/home.component.html";
// console.log($location.path());
//console.log(this.router);
this.router.navigate(['/home']);
console.log("GREAT!");
}
return true;
}
);
}
}
my app.module.ts looks like so:
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BooksComponent } from './books/books.component';
import { HomeComponent } from './home/home.component';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { RouterModule, Routes } from '#angular/router';
#NgModule({
declarations: [
AppComponent,
BooksComponent,
HomeComponent,
],
imports: [
RouterModule.forRoot([
{
path: 'home',
component: HomeComponent
}
]),
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
my books.component.ts and books.component.html files are in my books directory.
my home.component.ts and home.component.html files are in my home directory
I've attached a screenshot of how my directory structure looks like.
So far I'm trying to use this.router.navigate but I'm not having much luck with that.
Any help would be greatly appreciated!
EDIT
My home.component.ts file looks like so:
import { Component } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent {
constructor() { }
}
As we discussed - here is the solution - hope it works
Add only <router-outlet></router-outlet> on app.compoment.html and using routing try to render the components
Your route should read as
RouterModule.forRoot([
{
path: 'home',
component: HomeComponent
},
{
path: 'book',
component: BookComponent
},
{
path: '',
redirectTo: 'book'
pathMatch: 'full'
}
])
Thus on the initial load your path will match empty and redirect to BookComponent and inside the book component when you navigate it will load the HomeComponent inside the AppComponent html
Hope this might solve your problem - happy coding :-)
I'm using the RouterModule and have a problem with the routerLinks.
The routerLinks doesn't work (the anchor isn't clickable) because they are in a child module and I don't know how to fix this problem.
Hierarchy:
App.Module (router-outlet) -> Elements Module -> Navi Module (routerLinks)
app.module.ts
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { RouterModule } from '#angular/router';
import { HttpClientModule } from '#angular/common/http';
import { ElementsModule } from './elements/elements.module';
import { LandingComponent } from './pages/landing.component';
import { GenreComponent } from './pages/genre.component';
import { SinglePostComponent } from './pages/singlepost.component';
import { ListComponent } from './pages/list.component';
import { AppComponent } from './app.component';
import { DataService } from './data.service';
#NgModule({
imports: [
BrowserModule,
ElementsModule,
HttpClientModule,
RouterModule.forRoot([
{path: "", component: LandingComponent},
{path: "post/:id", component: SinglePostComponent},
{path: "lists", component: ListComponent}
], {
useHash: true,
})
],
declarations: [
AppComponent,
LandingComponent,
GenreComponent,
SinglePostComponent,
ListComponent
],
providers: [DataService],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
<router-outlet></router-outlet>
navi.componentent.html
<a routerLink="/movies">Movies</a>
In my project I have an module specified for handling routes and that my other modules can import:
app-routing.module.ts:
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
import { MainComponent } from './main/main.component';
const routes: Routes = [
{
path: '',
component: MainComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
This is imported by my other modules like:
#NgModule({
declarations: [
AppComponent,
MainComponent
],
imports: [
AppRoutingModule
]
})
export class AppModule {}
I have an Angular 4 application with login and registration page and then we I have this interface to manage my employees and stuff like that.
I want to launch my application on a specific page which is login page, like:
http://localhost:4200/login
How to make login page appear once Angular is started and the URL contains /login segment in it ?
here is my app.module.ts file:
import { UserService } from './user.service';
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { HttpModule } from '#angular/http';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { MatButtonModule, MatCardModule, MatMenuModule, MatToolbarModule, MatIconModule, MatInputModule,MatAutocompleteModule } from '#angular/material';
import { MatFormFieldModule } from '#angular/material';
import { FormsModule, ReactiveFormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { UserComponent } from './user/user.component';
import { RouterModule } from '#angular/router';
import { HomeComponent } from './home/home.component';
import { LoginComponent } from './login/login.component';
// Define the routes
#NgModule({
declarations: [
AppComponent,
UserComponent,
HomeComponent,
LoginComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
HttpModule ,
RouterModule.forRoot([
{
path: 'home',
component: HomeComponent
},
{
path: 'users',
component: UserComponent
}
{
path: 'login',
component: LoginComponent
}
]),
BrowserAnimationsModule,
MatButtonModule,
MatCardModule,
MatMenuModule,
MatToolbarModule,
MatIconModule,
MatInputModule,
MatFormFieldModule,
MatAutocompleteModule
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
Use Empty-path route configurations
Add
{path: '' , redirectTo:'/login',pathMatch:'full'} to your routes.
Try this in to your routes
{ path: '**', redirectTo: '/login', pathMatch: 'full' }
Env:
Angular2-webpack bolierplate : https://github.com/preboot/angular2-webpack
nodejs 6.3.1 / npm 3.10.3
When I run a karma test an error occurs but It seems works well while server running.
SUMMARY:
✔ 2 tests completed
✖ 1 test failed
FAILED TESTS:
Home Component
✖ should ...
Chrome 55.0.2883 (Mac OS X 10.12.2)
Error: Template parse errors:
'my-searchbar' is not a known element:
1. If 'my-searchbar' is an Angular component, then verify that it is part of this module.
2. If 'my-searchbar' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schemas' of this component to suppress this message. ("d="go_mypage" href="/mypage"><img src="/img/mypage-thin.png"></a>
<div class="fold" id="wrapper">
[ERROR ->]<my-searchbar></my-searchbar>
<span>Home Works!</span>
</div>"): HomeComponent#2:2
...
I have looked at several stack overflow questions or other websites related with this error but They were not very helpful.
app.module.ts
import { NgModule, ApplicationRef } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { HttpModule } from '#angular/http';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { MypageComponent } from './mypage/mypage.component';
import { HomeModule } from './home/home.module';
import { ApiService } from './shared';
import { routing } from './app.routing';
import { removeNgStyles, createNewHosts } from '#angularclass/hmr';
#NgModule({
imports: [
BrowserModule,
HttpModule,
FormsModule,
routing,
HomeModule
],
declarations: [
AppComponent,
MypageComponent
],
providers: [
ApiService
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(public appRef: ApplicationRef) {}
hmrOnInit(store) {
console.log('HMR store', store);
}
hmrOnDestroy(store) {
let cmpLocation = this.appRef.components.map(cmp => cmp.location.nativeElement);
// recreate elements
store.disposeOldHosts = createNewHosts(cmpLocation);
// remove styles
removeNgStyles();
}
hmrAfterDestroy(store) {
// display new elements
store.disposeOldHosts();
delete store.disposeOldHosts;
}
}
app.component.html
<main>
<router-outlet></router-outlet>
</main>
./home/home.component.html
<a class="route" id="go_mypage" href="/mypage"><img src="/img/mypage-thin.png"></a>
<div class="fold" id="wrapper">
<my-searchbar></my-searchbar>
<span>Home Works!</span>
</div>
./home/home.module.ts
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { RouterModule } from '#angular/router';
import { HomeComponent } from './home.component';
import { SearchbarComponent } from './searchbar.component';
#NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule
],
declarations: [
HomeComponent,
SearchbarComponent
],
exports: [
HomeComponent,
SearchbarComponent
]
})
export class HomeModule { }
--Update--
./home/searchbar.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'my-searchbar',
templateUrl: './searchbar.component.html',
styleUrls: ['./style/searchbar.component.scss']
})
export class SearchbarComponent {
searchWord: string;
searchTag: string[];
onKey(event: any) {
console.log(event.key);
}
}
home.component.spec.ts
// This shows a different way of testing a component, check about for a simpler one
import { Component } from '#angular/core';
import { TestBed } from '#angular/core/testing';
import { HomeComponent } from './home.component';
describe('Home Component', () => {
const html = '<my-home></my-home>';
beforeEach(() => {
TestBed.configureTestingModule({declarations: [HomeComponent, TestComponent]});
TestBed.overrideComponent(TestComponent, { set: { template: html }});
});
it('should ...', () => {
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
expect(fixture.nativeElement.children[0].textContent).toContain('Home Works!');
});
});
#Component({selector: 'my-test', template: ''})
class TestComponent { }
The error/warning is explanatory, so pretty much what it says there:
You have created a custom element, <my-searchbar></my-searchbar> which is not a known Angular 2 element, and to suppress the warning add it to schemas in NgModule like so:
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
I am using NgModule in angular2, 2.0.0-rc.5 but I got the error shim.js:4035 Unhandled promise rejection Error: Cannot match any routes: ''(…). How can I resolve this error.Please help me here is my code.
app/base/app.component.html
<router-outlet></router-outlet>
app/base/app.component.ts
import { Component } from '#angular/core';
import { ROUTER_DIRECTIVES } from '#angular/router';
import { EventService } from '../shared/service/event-service';
#Component({
moduleId: module.id,
selector: 'owb-workbench-app',
templateUrl: 'app.component.html',
providers: [EventService],
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent {
}
app/base/app.module.ts
import { provide } from '#angular/core';
import {CommonModule, APP_BASE_HREF} from "#angular/common";
import { disableDeprecatedForms, provideForms } from '#angular/forms/index';
import { enableProdMode } from '#angular/core';
import { bootstrap } from '#angular/platform-browser-dynamic';
import { LocationStrategy, HashLocationStrategy } from '#angular/common';
import { HTTP_PROVIDERS, HttpModule } from '#angular/http';
import { HttpClient } from '../shared/http/base.http';
import { EventService } from '../shared/service/event-service';
import { routing } from './app.routes';
import { DashboardComponent } from '../dashboard/dashboard.component'
import { appRoutingProviders } from './app.routes'
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { FormsModule } from '#angular/forms';
import { AppComponent } from './app.component';
import { NKDatetime } from 'ng2-datetime/ng2-datetime';
#NgModule({
imports: [ BrowserModule, FormsModule,HttpModule,CommonModule,routing,appRoutingProviders],
declarations: [ AppComponent, NKDatetime,DashboardComponent],
exports: [NKDatetime],
bootstrap: [ AppComponent ],
providers: [{ provide: LocationStrategy, useClass: HashLocationStrategy },
{ provide: APP_BASE_HREF, useValue: '<%= APP_BASE %>' },
HTTP_PROVIDERS,EventService,HttpClient]
})
export class AppModule {
}
app/base/app.routes.ts
import { provideRouter, RouterConfig,RouterModule,Routes } from '#angular/router';
import { ModuleWithProviders } from '#angular/core';
import { DashboardRoutes } from '../dashboard/index';
export const routes: RouterConfig = [
...DashboardRoutes
];
export const appRoutingProviders: any[] = [];
export const routing: ModuleWithProviders = RouterModule.forRoot(routes);
app/base/main.ts
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app.module';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
app/dashboard/dashboard.component.html
<h1>Hello World Welcome</h1>
app/dashboard/dashboard.component.ts
import { Component } from '#angular/core';
import { ROUTER_DIRECTIVES } from '#angular/router';
import { TopNavComponent } from '../shared/topnav/topnav';
import { SidebarComponent } from '../shared/sidebar/sidebar';
import { RightNavComponent } from '../shared/rightnav/rightnav';
#Component({
moduleId: module.id,
selector: 'dashboard-app',
templateUrl: 'dashboard.component.html',
directives: [ ROUTER_DIRECTIVES, TopNavComponent, SidebarComponent, RightNavComponent ]
})
export class DashboardComponent {}
app/dashboard/dashboard.routes.ts
import { DashboardComponent } from './index';
import { ModuleWithProviders } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { GridViewComponent } from './+gridview/gridview.component'
const appRoutes: Routes = [
{
path: 'dashboard',
component: DashboardComponent
}
];
export const appRoutingProviders: any[] = [
];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);
app/dashboard/index.ts
/**
* This barrel file provides the export for the lazy loaded DashboardComponent.
*/
export * from './dashboard.component';
export * from './dashboard.routes';
You have to import your routes into the app.module.ts like this. I believe you also need to provide an empty route. In this case, home is my default route, you would change it to be dashboard if that's what your default is.
export const appRoutes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', loadChildren: './app/home/home.module#HomeModule' },
];
export const appRoutingProviders: any[] = [];
My app.module.ts (notice the RouterModule.forRoot(appRoutes) import):
#NgModule({
imports: [ BrowserModule, RouterModule.forRoot(appRoutes), SharedModule.forRoot() ],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [ appRoutingProviders ]
})
export class AppModule {}