Angular 5 Routing - Navigate to route by typing URL into address bar returns Handler for Request not found (404) - angular-routing

I am using Angular 5 to talk to a Service Stack back end.
I can load my home page by typing in the root address: http://127.0.0.1:8088 and from there I can navigate to all my defined routes using the relevant links.
However if I try to manually type in a route, i.e. http://127.0.0.1:8088/home or http://127.0.0.1:8088/searcharchive I get:
Handler for Request not found (404):
Request.HttpMethod: GET
Request.PathInfo: /home
Request.QueryString: Request.RawUrl: /home
My routing codes is as follows:
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: 'searcharchive', component: SearchArchiveComponent },
{path: '', redirectTo: 'home', pathMatch: 'full'},
{path: '**', component: PageNotFoundComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
And the HTML template is:
<nav>
<a [routerLink]="['/home']">Home</a>
<br/>
<a [routerLink]="['/searcharchive']">Search Archive</a>
<br>
<div class="container-admin-nav">
<a [routerLink]="['/admin']">Admin Module</a>
</div>
</nav>
This is causing a real headache as not only can I not navigate using the address bar I cannot even do simple things like adding images, as no matter where I place the image It can't be displayed. When looking at the developer tools I get GET http://127.0.0.1:8088/logoTransparent.png 404 (Not Found) so I can only surmise that routing is (once again) getting in the way some how.

I had a similar problem because I was using
proxy configuration.
Angular app was my front-end and I had a SpringBoot app as back-end.
In my proxy.config.json file I had the following:
{
"/**": { <-- **marked line**
"target": {
"host": "localhost",
"protocol": "http:",
"port": 8080
},
"secure": false,
"logLevel": "debug"
}
}
So, whenever I typed in any route in the address bar, it would get rerouted to my SpringBoot app because of the marked line... and I didn't want that. I just wanted my back-end requests from my services to be rerouted to my back-end.
Solution:
I added /api to my back-end requests (in all my services) and then, in proxy.config.json I just removed /api from the url. To achieve this, I just added "pathRewrite": { "^/api": "" }, to my proxy.config.json which now looked like this:
{
"/api/**": {
"target": {
"host": "localhost",
"protocol": "http:",
"port": 8080
},
"pathRewrite": {
"^/api": ""
},
"secure": false,
"logLevel": "debug"
}
}

Related

What is the right way to define child routes in Spartacus?

I am working in a B2B Spartacus project and we are currently implementing the MyCompany User/Unit management. The Spartacus implementation is a little to complex for our use-case so we are developing a custom solution based on it.
The original implementation features a CMS-Page for users (e.g.: https://spartacus-demo.eastus.cloudapp.azure.com:444/powertools-spa/en/USD/organization/users) and then Angular child routes for the user details (e.g.: /organization/users/7a95e933-364c-4c8d-81cd-4f290df0faf1)
I tried to replicate the child route implementation following the Spartacus documentation.
I created a parent (RightsManagementUser) and child (RightsManagementUserDetails) component.
<p>rights-management-user works!</p>
<a
class="btn btn-primary"
[routerLink]="{
cxRoute: 'orgUserDetails',
params: { customerId: '9e26d9fb-14eb-4ec6-9697-3fa53302245c' }
} | cxUrl"
>Go to User Details</a
>
<router-outlet></router-outlet>
Following the Spartacus Documentation, I provided a Spartacus and an Angular routing config
export const userRoutingConfig: RoutingConfig = {
routing: {
routes: {
orgUser: {
paths: ['organization/users'],
},
orgUserDetails: {
paths: ['organization/users/:userCode'],
paramsMapping: {
userCode: 'customerId',
},
},
},
},
};
RouterModule.forChild([
{
path: null,
component: PageLayoutComponent,
canActivate: [CmsPageGuard],
data: { cxRoute: 'orgUser' },
children: [
{
path: null,
component: RightsManagementUserDetailsComponent,
data: { cxRoute: 'orgUserDetails' }
},
],
},
]),
I also tried following the documentation for Adding Angular Child Routes for a Content Page
and added the child route to the cms config.
RightsManagementUserComponent: {
component: RightsManagementUserComponent,
childRoutes: [
{
path: ':userCode',
component: RightsManagementUserDetailsComponent,
},
],
},
This all wasn't enough, when clicking the button, the CMSPageGuard tries to load the CMS page for /organization/users/7a95e933-364c-4c8d-81cd-4f290df0faf1 instead of activating the child route.
I then tried to go the Angular way and defined the child route without using cxRoute:
children: [
{
path: ':userCode',
component: PflRightsManagementUserDetailsComponent,
},
],
At first I was happy, since the child route actually activated:
But then I realized that when I do a browser refresh Spartacus again tries to access the CMS-Page instead of activating the route.
Can someone please help me out and point me to the right way to use child routes in Spartacus?
If you would like to use split view, you can define your route in this way #customizing-routes, then clone whole cms configuration for organization feature and personalize childs #customizing-cms-components.
It could looks like:
const yourConfig = { ...userCmsConfig.cmsComponents.ManageUsersListComponent };
(yourConfig.childRoutes as CmsComponentChildRoutesConfig).children[1].component = RightsManagementUserDetailsComponent;
and include in your module
imports: [
// ...
B2bStorefrontModule.withConfig({
// ...
cmsComponents: {
ManageUsersListComponent: yourConfig,
},
},
// ...

Angular routerLink routes properly but route.navigate in component routes to default path

The Basic Sample is created
The Source Code is Uploaded Here
and Deployed Here
A route is set with path :"products"
In app.template.html using routerLink directive a route is set ->
when "Products" gets clicked --> The route "products" is opened as
expected, but activating the same route through code
(this.route.navigate(['/products']) in "app.component.ts" navigates
to this 'home'.
This is basic but weird, where have I gone wrong ?
It's getting redirected on your app.component.html on line 19:
<a class="nav-link" href="#" (click)="navigateBack()"> Products(navigated in Component)</a>
This tag has href="#" so the page is getting routed to your root because your app-routing.module.ts file is redirecting to home.
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: '**', redirectTo: 'home', pathMatch: 'full' }
So, remove href="#" with [routerLink]="[]" and it should resolve the issue.

Angular Routing - Direct path access not working from URL

I created and host www.xinthose.com. This is the source code for the website. When you navigate to the website, it will take you to the path /home, but when you try to duplicate that tab or go directly to www.xinthose.com/home, I get a 404 error from HostGater (my website host). This is the contents of app-routing.module.ts:
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { HomeComponent } from './home/home.component';
import { BibleComponent } from './bible/bible.component';
import { AboutComponent } from './about/about.component';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'bible', component: BibleComponent },
{ path: 'about', component: AboutComponent },
{ path: '**', component: PageNotFoundComponent },
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
Why is this happening and how do I fix it? Is it related to pathMatch at all? Am I missing some Route property?
Alternative solution, May 2022:
This is probably a very late answer and I see that you have already solved your question. However, here is an alternative (free hosting but depending on the services you use it can be paid):
You can use Firebase Hosting to host your angular application for free. There is the possibility to also use your own domain if you don't want to use the default urls generated from Firebase. I had initially hosted my application elsewhere, which resulted in the same problem that you described above, however hosting the application using Firebase solved this issue for me.
You can implement firebase in your application simply from the Firebase documentation (link above) or a simpler solution is to implement it using angular/angularfire which is the official implementation of Firebase for Angular. Please install the library with ng add #angular/fire and follow the instructions given in the terminal.
This is not because of the web app route roles.
Angular applications have to become installed , and available so , angular router can be usable , so , when ever you try to access route like this 'domain/home' , you will get 404 error.
There is three solution that i know right now
1st 'best'
Angular universal
2nd
If your host is something like apache , that use php files, try to rewrite routes like this
search for rewrite urls for any other kind of host servers
.htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.domain.com$ [NC]
RewriteRule ^(.*)$ https://app.domain.com/$1 [L,R=301]
3rd
Use PWA
this one is awesome, but still , application have to be installed on user device , but after first launch , direct routes will work
It took me almost a year, but I figured out that you have to pay for node.js hosting, AWS elastic beanstalk is a good candidate for this. Then you have to serve your static compiled website using something like express.js. This is my working example server.js:
"use strict";
const express = require("express");
const compression = require('compression');
// config
const port = process.env.PORT || 3000;
const app_folder = "./";
const options = {
dotfiles: 'ignore',
etag: false,
extensions: ['html', 'js', 'scss', 'css'],
index: false,
maxAge: '1y',
redirect: true,
}
// create app
const app = express();
app.use(compression());
app.use(express.static(app_folder, options));
// serve angular paths
app.all('*', function (req, res) {
res.status(200).sendFile(`/`, {root: app_folder});
});
// start listening
app.listen(port, function () {
console.log("Node Express server for " + app.name + " listening on http://localhost:" + port);
});
Then in package.json you have a start command the website host will run:
{
"name": "xinthose.com",
"scripts": {
"ng": "ng",
"start": "node server.js",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"dependencies": {...},
"devDependencies": {...}
}
This is the only way to serve pages dynamically on a static single page application.

ionic nav push params not shown in url

app.module.ts:
imports: [
IonicModule.forRoot(MyApp, {}, {
links: [
{ component: CategoryPage, name: 'Category', segment: 'category:id'}
]
}
],
providers: [
{
provide: LocationStrategy,
useClass: PathLocationStrategy
}
]
Configuration of the page I am navigating too
#IonicPage({
name: 'Category',
segment: 'category/:id'
})
Code which triggers navigation:
this.nav.push(CategoryPage, {id: 3});
The component does load as expected and I can call this.navParams.get('id') which yields 3 from within the components class.
Expected result: The url changes to /category:3
Observed result: The url changes to /category:id
so if you are trying to implement deep links for Ionic 3 (since Ionic 4 is using Angular's router by default now) you need to ensure you also configure each page accordingly.
The page you are navigating to needs to have configs added via #IonicPage:
#IonicPage({
segment: 'second/:id'
})
See more in ionic docs or this guide

Angular2 HTTP Request Providers

I want to make connection between my angular app and my REST API.
Here it returns JSON http://is.njn.mvm.bg/check. So my question is which providers do I need because I include in app.module, but it still doesn't work.
import { HttpModule} from '#angular/http';
I am using Angular2 HTTP tutorial
private heroesUrl = 'http://is.njn.mvm.bg/check'; // URL to web API
constructor (private http: Http) {}
getHeroes (): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
I am getting XMLHttpRequest cannot load http://localhost:8000/da. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
you are using the http request wrong. plz use following code.
app.component.ts
//our root app component
import { Component } from '#angular/core'
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'root',
template: `
<div>
{{people}}
{{ err}}
</div>
`
})
export class App {
people;
err;
constructor(http:Http) {
http.get('http://is.njn.mvm.bg/check').map(res => res.text()).subscribe(people => this.people = people,err=>this.err = err);
// Subscribe to the observable to get the parsed people object and attach it to the
// component
}
}
Also remember
Follow error occur in your console:
Access-control-allow-origin
For remove this error see:
chrome extension for access control
You need to put header parameter "Access-Control-Allow-Origin" in the server's HTTP response. You can't make this work from the client side only. I also had the same issue when trying to grab data from my Java JSON REST server. I am not sure what you use server side, but in Java it looks something like this:
return Response.ok() //200
.header("Access-Control-Allow-Origin", "*");
For information on this error (CORS), see this:
How does Access-Control-Allow-Origin header work?
You also need to add it to imports of #NgModule
#NgModule({
imports: [BrowserModule, HttpModule]
...
})
You module code will be like below:
#NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
],
declarations: [
AppComponent
],
providers: [
{provide: APP_BASE_HREF, useValue: '/'},
],
bootstrap: [AppComponent]
})
export class AppModule {
}
you service code need to similar to this
constructor(private http: Http) {
}
getCountriesByRegion(region: string) {
return this.http.get(this.countries_endpoint_url + region).map(res => res.json());
}
//you can also do like this
getHeroes(): Observable<any[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
You have the Angular app that's served by the server running on port 3000, but this app tries to make HTTP calls to the server running on another port 8000.
You have two options:
1. Deploy your Angular app under the server that runs on port 8000, in which case your Angular app will hit the same port it was served from.
2. Configure a proxy on the server that runs on port 3000 to allow access to port 8000.
For the second scenario, if you use Angular CLI with your project, create a file proxy-conf.json, for example:
{
 "/api": {
 "target": "http://localhost:8000",
 "secure": false
 }
}
Then sevre your Anglar app like this:
ng serve --proxy-config proxy-conf.json