简体   繁体   中英

How do I reuse Angular form on server side for validation?

I want to reuse same set of validators on client and server side with Angular 4.4.5 and NodeJS 7.10.1 (latest in Ubuntu repos). I believe it's possible.

My basic idea is to have HTTP endpoint working on NodeJS and Express which accepts POST request with JSON data from Angular form, creates same form with received data and checks it.

My attempts were unsuccessful, I don't know how to use same version of Typescript as Angular uses and how to import component with form. It would be ideal to see some simple example that work. I'll share my attempts soon.

By now I managed to instantiate Component this way.

Create cli.ts to test standalone creation of Angular component:

import 'reflect-metadata';
import { CuComponent } from './app/cu.component';

console.log(new CuComponent())

Run tsc with some settings from tsconfig.json :

tsc -t es5 --lib es2016,dom --experimentalDecorators src/cli.ts

Got output:

CuComponent {
  registration: 
   FormGroup {
     validator: null,
     asyncValidator: null,
     _onCollectionChange: [Function],
     _pristine: true,
     _touched: false,
     _onDisabledChange: [],
     controls: { familyName: [Object], givenName: [Object], phone: [Object] },
     _valueChanges: 
      EventEmitter {
        _isScalar: false,
        observers: [],
        closed: false,
        isStopped: false,
        hasError: false,
        thrownError: null,
        __isAsync: false },
     _statusChanges: 
      EventEmitter {
        _isScalar: false,
        observers: [],
        closed: false,
        isStopped: false,
        hasError: false,
        thrownError: null,
        __isAsync: false },
     _status: 'VALID',
     _value: { familyName: null, givenName: null, phone: null },
     _errors: null } }

Component is created.

After a long search I found a solution. Angular now supports workspaces with libraries and server side rendering of forms (ssr) using Node and Express.js. So Angular 8+ basically already has everything needed.

What I do is I put all my shared code in a library so I can use it in the frontend and also reuse it on a SSR app (validation). I don't think that this is necessary, but a clean structure is helpful.

To create the structure I just used the cli:

  • Create new workspace.
  • Generate library for shared code.
  • Generate application for the frontend (normal ng app).
  • Generate application for the validation server and run ng add @nguniversal/express-engine on it.

You can find all relevant information on how to do this in the tutorials:

Now I used the generated server.ts and deleted most of it (example handlers). At fist, I had some problem with JSON parsing. But the body-parser can do it.

// ...
import * as bodyParser from "body-parser";
// ...
export function app() {
  const server = express();
  server.use(bodyParser.json());
  // ...

Then I added this handler:

  server.post('/api/validate', (req, res) => {
    // createFormGroup is from my code, 
    // because I generate the form from TypeScript classes.
    // You can just use a FormBuilder in your component 
    // and export the function so you can use it here.
    const fg = createFormGroup();     
    fg.patchValue(req.body);
    res.status(200).send({
        "accepted" : "VALID" === fg.status
        // You can send additional information, like errors
      });
  });

Calling fg.updateValueAndValidity() does not seem to be necessary as patchValue already does all that.

Time to build and start the server.
Somehow I now have a problem where the build script doesn't work with --prod . But this does:
ng build; ng run validation:server:production; npm run serve:ssr

You should get:
Node Express server listening on http://localhost:4000

And that's it. Really easy.

I use curl for testing:

curl.exe --data "@data.json" -H "Content-Type: application/json" -X POST http://localhost:4000/api/validate

I don't know how to debug this, but console.log works just fine. And to test the code that you use on this server you should just use unit tests (jasmine) anyway. So even though this is slow to start I'm just glad I can now validate code on the server.

It might make sense to compare req.body and fg.value recursively for equality, to make sure it's still the same data after validation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM