0

I would like to display my error message in my jade view after validation.

Jade

    H1 Hello world
#error
  p  #{JSON.stringify(errorMsg)}
div
  form(action="/",method="post")
    div Foo
    div
      input(type="text",name="foo")
    div
      input(type="submit",name="submit")

This is my server code...

server.register(Vision,(err)=>{
     if(err){console.log(err)}

  server.views({
    engines:{
      jade:Jade
    },
    path: 'views',
    relativeTo: __dirname   });
     server.route([
    {
      method:'GET',path:'/',
        handler:(request,reply)=>{

          reply.view('index');
        }
      },
      {
        method:'POST',path:'/',
          handler: (request,reply) => {
          console.log("POST '/' ");

          const err = {}; // check error and set it
          reply.view('index',{errorMsg:err});
        },
         config:{
      validate:{
        payload: {
            foo: Joi.string().required(),
            submit:Joi.string().required()
        }
      }
    }
      }
     ]); });

server.start((err)=>{
     if(err){console.log(err);}   console.log("server started:"+server.info.uri);

});

Goal is to validate the presence of foo

When the validation kicks in the server responses with a http 400 error which is totally fine and expected for api's. This happens even before the handler function is called.

What is the best way to handle validation error with using a view engine?

I was expecting something like (which is obviously not working)

if(request.error){
    reply.view('index',{errorMsg:err});
    }

I saw also some answers who dealed with the onPreResponse event to catch it globally. Isn't their a way to do this in the request handler method? Or any best practise tips?

silverfighter
  • 6,762
  • 10
  • 46
  • 73

2 Answers2

0

The docs cover this situation specifically. See the specifics here.

The short version taken directly from the docs looks like this:

const preResponse = function (request, reply) {

    const response = request.response;
    if (!response.isBoom) {
        return reply.continue();
    }

    // Replace error with friendly HTML

      const error = response;
      const ctx = {
          message: (error.output.statusCode === 404 ? 'page not found' : 'something went wrong')
      };

      return reply.view('error', ctx);
};

server.ext('onPreResponse', preResponse);

Basically on the preResponse event, check if the response is a boom object. If not, reply normally. If is is a boom object reply with your error page and pass some data into it.

arb
  • 7,753
  • 7
  • 31
  • 66
  • Thanks, I saw that. But my question was more towards a single context vs a global context (404). For example: post registration form and if validation failed then flash a message on the same view. Like shown above in the error div. Also with context specific error messages like username required. – silverfighter Mar 02 '16 at 16:17
0

If you are using a JOI object to validate the payload you cannot handle it in the handler.

If you log out the request lifecycle:

server.route({
  method: 'POST',
  path: '/',
  handler: (req, reply) => {
    reply('hello');
    console.log('handler');
  },
  config: {
    validate: {
      payload: {
        date: Joi.date().required(),
      },
    },
  },
});

server.ext('onRequest', (request, reply) => {
  console.log('onRequest');
  reply.continue();
});

server.ext('onPreAuth', (request, reply) => {
  console.log('onPreAuth');
  reply.continue();
});

server.ext('onPostAuth', (request, reply) => {
  console.log('onPostAuth');
  reply.continue();
});

server.ext('onPreHandler', (request, reply) => {
  console.log('onPreHandler');
  reply.continue();
});

server.ext('onPostHandler', (request, reply) => {
  console.log('onPostHandler');
  reply.continue();
});


server.ext('onPreResponse', (request, reply) => {
  console.log('onPreResponse');
  reply.continue();
});

And try a valid "date" parameter you will get:

onRequest
onPreAuth
onPostAuth
onPreHandler
handler
onPostHandler
onPreResponse

When you try an invalid parameter, so the validation fails:

onRequest
onPreAuth
onPostAuth
onPreResponse

As you can see the handler is not called at all so you cannot handle it the way you described.

If you don't want to implement the routes as an API and then consume it by your site, I would recommend removing the validate attribute from your config and use Joi.validate() in you handler like so:

server.route({
  method: 'POST',
  path: '/',
  handler: (req, reply) => {
    Joi.validate(req.payload, dateSchema, (err, val) => {
      if (err) {
        reply.view('index', { error: err });
      }

      reply('the date is valid');
    });
  },
});

Remember that Joi is throwing an error object so it's not just text.

kyrisu
  • 4,541
  • 10
  • 43
  • 66
  • Thanks for your reply...Wouldn't this also fire for every other route as well? This looks like the general Request flow, right? – silverfighter Mar 03 '16 at 08:55
  • If you are thinking about pre- hooks - yes they would. I just wanted to show the lifecycle and why it's not possible to handle error codes in the handler. Matt Harrison (author of Hapi.js in Action) has a nice diagram of the flow: https://twitter.com/mt_harrison/status/602731699584176129 You can see on it where the validation in taking place. – kyrisu Mar 03 '16 at 09:12