0

App.js

var express = require('express');
var path = require('path');
var logger = require('morgan');
var bodyParser = require('body-parser');


var statements = require('./routes/route');
var app = express();



app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ 'extended': 'false' }));
app.use(express.static(path.join(__dirname, 'dist/statement-rater-app')));

app.use('/', express.static(path.join(__dirname, 'statement-rater-app')));
app.use('/api/v1/statements', statements);
//app.use('/images', express.static('images'))

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  //console.log(res);
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function (err, req, res, next) {
  // set locals, only providing error in development
  console.log(err.message);
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  console.log("this is where it's happening");
  
  // render the error page
  res.status(err.status || 500);
  res.json({ error: err })
});

module.exports = app;

Angular Routing

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { CompanyListComponent } from './company-list/company-list.component';

const routes: Routes = [
  {
    path: '', 
    component: HomeComponent, 
    //canActivate: [MsalGuard]
  }, 
  {
    path: 'company-list',
    component: CompanyListComponent
  }
  


];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

AppComponent HTML

<mat-toolbar class="mat-elevation-z2">
  <div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
    <span fxFlex class="team-logo"><img src="../assets/images/logo.png" alt="Logo" aria-label="logo" width="100" /> </span>
  </div>
  <span fxFlex></span>
  <div fxFlex = "20">
    <mat-nav-list fxFlex fxLayout="row">
      <a mat-list-item [routerLink]="['/']" routerLinkActive="active" target="_top"> <mat-icon>home</mat-icon> Home</a>
      <a mat-list-item [routerLink]="['company-list']" routerLinkActive="active" target="_top"><mat-icon>list</mat-icon> List</a>
      <a mat-list-item [routerLink]="['logout']" routerLinkActive="active" target="_top"><mat-icon>clear</mat-icon> Logout</a>
    </mat-nav-list>
  </div>
</mat-toolbar>

<router-outlet></router-outlet>

I have this node.js and angular app that works fine with a single link (home). I can do everything on this, but when I added another link on the HTML, the home link still works, but company-list shows the following error:

{"error":{"status":404}}

I have no idea what's going on and how to fix. I googled and tried solutions that were found on RouterLink does not work and a few other places but the link still shows that error. What's happening?

Update

As suggested, I also added the folllowing code, but I'm still getting similar error.

 app.all('/*', function (req, res) {
  res.status(200).sendFile(`/` + __dirname );
});

This is the error I get:

{"error":{"errno":-4058,"code":"ENOENT","syscall":"stat","path":"C:\\Users\\username\\source\\repos\\statement-rater-appstatement-rater-app","expose":false,"statusCode":404,"status":404}}
Kuni
  • 817
  • 1
  • 9
  • 24
  • @R. Richards. Sorry about that. When I tried to post last time, the page didn't refresh automatically so I manually did it. Apparently, it created two posts. I'll delete the other one. Thanks for pointing that out. – Kuni Oct 20 '20 at 16:56
  • To serve the angular application as a SPA, you need to add a fallback route `app.use('*'` to route all requests that don't match your API routes to the angular built index.html. This isn't specific to Angular. The solution can be seen in questions such as https://stackoverflow.com/questions/25498775/configure-express-to-send-index-html-for-every-url-except-those-ending-in-css-a – Alexander Staroselsky Oct 20 '20 at 17:02
  • Does this answer your question? [Configure Express to send index.html for every url EXCEPT those ending in .css and .js](https://stackoverflow.com/questions/25498775/configure-express-to-send-index-html-for-every-url-except-those-ending-in-css-a) – Alexander Staroselsky Oct 20 '20 at 17:03
  • the idea is that company-list should not hit backend at all; if you use routerLink as described. Of course if you link from outside, some config on express side might be useful. – Normunds Kalnberzins Oct 20 '20 at 17:06
  • @NormundsKalnberzins, That is exactly what I'm confused about. the routerLink `company-list` was not supposed to hit the backend. I have used similar code for my other apps and they work fine. It's just this that is not working and I can not figure out what is happening that's making routerlink to hit the backend. – Kuni Oct 20 '20 at 17:11
  • https://stackoverflow.com/questions/30546524/making-angular-routes-work-with-express-routes – Phix Oct 20 '20 at 18:50
  • @Phix, none of the above mentioned potential solutions worked for me – Kuni Oct 20 '20 at 19:31

1 Answers1

0

this is so strange and annoying. All it took was a slash() in front of the text in the routerLink.

<mat-nav-list fxFlex fxLayout="row">
  <a mat-list-item [routerLink]="['/']" routerLinkActive="active" target="_top"> <mat-icon>home</mat-icon> Home</a>
  <a mat-list-item [routerLink]="['/company-list']" routerLinkActive="active" target="_top"><mat-icon>list</mat-icon> List</a>
  <a mat-list-item [routerLink]="['/logout']" routerLinkActive="active" target="_top"><mat-icon>clear</mat-icon> Logout</a>
</mat-nav-list>
Kuni
  • 817
  • 1
  • 9
  • 24