Integrating Loopback 4 and Angular 8

473 Views Asked by At

I am new to loopback. Started with Loopback 4. I am trying to create a simple 'Hello world' application using Loopback4 and Angular8.

In my application.ts, I am pointing my static directive path to my angular application src folder.

// Set up default home page
    this.static('/', path.join(__dirname, '../angular-app/src'));

So I can see normal HTML content from index.html file from angular-app/src/index.html file, but it doesn't bind anything inside <app-root> </app-root>

I see in Loopback v3, middleware.json was used to host client application like this:

"files": {
"loopback#static": {
"params": "$!../client"
 }
}

What I'm doing wrong here?

Thanks in advance.

2

There are 2 best solutions below

1
On

I've managed to get it work in Loopback 4 with Angular 9. After an angular app ng build the contents of the dist/\<app-name\> folder should be placed inside the loopback public folder.

Then, in order for the angular router to work properly, all the HTML errors ( Specifically 404 Not found errors) should be redirected to the angular index.html.

To do that we must bind RestBindings.SequenceActions.REJECT to a custom provider. In application.ts just include the new binding

this.bind(RestBindings.SequenceActions.REJECT).toInjectable(AngularRejectProvider);

The AngularRejectProvider could be taken from the default reject provider in @loopback/rest/src/providers/reject.provider.ts :

// Copyright IBM Corp. 2018,2020. All Rights Reserved.
// Node module: @loopback/rest
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {BindingScope, inject, injectable} from '@loopback/core';
import {HttpError} from 'http-errors';
import {ErrorWriterOptions, writeErrorToResponse} from 'strong-error-handler';
import {RestBindings} from '@loopback/rest';
import {HandlerContext, LogError, Reject} from '@loopback/rest';
// @ts-ignore
var accepts = require('accepts')
import path from 'path';

// TODO(bajtos) Make this mapping configurable at RestServer level,
// allow apps and extensions to contribute additional mappings.
const codeToStatusCodeMap: {[key: string]: number} = {
  ENTITY_NOT_FOUND: 404,
};

@injectable({scope: BindingScope.SINGLETON})
export class AngularRejectProvider {
  static value(
    @inject(RestBindings.SequenceActions.LOG_ERROR)
    logError: LogError,
    @inject(RestBindings.ERROR_WRITER_OPTIONS, {optional: true})
    errorWriterOptions?: ErrorWriterOptions,
  ): Reject {
    const reject: Reject = ({request, response}: HandlerContext, error) => {

      // ADD THIS
      const resolvedContentType = accepts(request).types([
        'text/html', 'html',
      ]);
      switch(resolvedContentType) {
        case 'text/html':
        case 'html':
          return response.sendFile(path.join(__dirname, '../../public/index.html'));;
      }
      // END ADD THIS

      const err = <HttpError>error;

      if (!err.status && !err.statusCode && err.code) {
        const customStatus = codeToStatusCodeMap[err.code];
        if (customStatus) {
          err.statusCode = customStatus;
        }
      }

      const statusCode = err.statusCode || err.status || 500;
      writeErrorToResponse(err, request, response, errorWriterOptions);
      logError(error, statusCode, request);
    };
    return reject;
  }
}

The new part is the following which basically redirects all HTML errors to angular:

const resolvedContentType = accepts(request).types([
            'text/html', 'html',
          ]);
          switch(resolvedContentType) {
            case 'text/html':
            case 'html':
              return response.sendFile(path.join(__dirname, '../../public/index.html'));;
          }
0
On

Do the following:

  • In terminal move to root app directory

  • Run

    $ng build

  • Replace

    this.static('/', path.join(__dirname, '../angular-app/src'));

    with

    this.static('/', path.join(__dirname, '../angular-app/www/index.html'));

Then test.

My guess is you are not building the angular project before putting your loopback server online. Whatever endpoint on which you are serving the angular application is sending a bunch of .ts files which browsers are not capable of displaying.

If the path I wrote is not the one, you might want to look for a new folder inside your project that wasn't there before you ran the build command. Inside there should be some directories, .js files with weird names and an index.html file.