Как использовать проверку в NestJS с рендерингом HTML?

#javascript #node.js #typescript #nestjs

#javascript #node.js #typescript #nestjs

Вопрос:

NestJS использует проверку с помощью каналов проверки и

 @UsePipes(ValidationPipe)
  

Если это не удается, выдается исключение. Это нормально для REST API, которые возвращают JSON.

Как можно проверить параметры при использовании рендеринга HTML и вернуть

 { errors: ['First error'] }
  

для шаблона hbs?

Комментарии:

1. Есть ли у вас один шаблон ошибки hbs, который вы хотите отобразить при ошибках, или ошибка должна отображаться в шаблоне hbs маршрута?

2. Ошибки должны отображаться в шаблоне hbs (в форме).

Ответ №1:

Вы можете создать Interceptor , который преобразует ошибку проверки в ответ на ошибку:

 @Injectable()
export class ErrorsInterceptor implements NestInterceptor {
  intercept(
    context: ExecutionContext,
    call$: Observable<any>,
  ): Observable<any> {
    return call$.pipe(
        // Here you can map (or rethrow) errors
        catchError(err => ({errors: [err.message]}),
      ),
    );
  }
}
  

Вы можете использовать его, добавив @UseInterceptors(ErrorsInterceptor) в свой контроллер или его методы.

Ответ №2:

Я сводил себя с ума, пытаясь найти «гнездовой» способ сделать это, сохраняя при этом некоторую степень настраиваемости, и я думаю, что наконец-то у меня это получилось. Во-первых, нам нужна ошибка, которая имеет ссылку на существующие class-validator ошибки, поэтому мы создаем пользовательский класс ошибок следующим образом:

 import { ValidationError } from 'class-validator';

export class ValidationFailedError extends Error {
  validationErrors: ValidationError[];
  target: any;

  constructor(validationErrors) {
    super();
    this.validationErrors = validationErrors;
    this.target = validationErrors[0].target
  }
}

  

(У нас также есть ссылка на класс, который мы пытались проверить, поэтому мы можем вернуть наш объект соответствующим образом)

Затем, в main.ts , мы можем установить пользовательскую фабрику исключений следующим образом:

   app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: (validationErrors: ValidationError[] = []) => {
        return new ValidationFailedError(validationErrors);
      },
    }),
  );
  

Далее мы создаем ExceptionFilter , чтобы перехватить нашу пользовательскую ошибку, вот так:

 
@Catch(ValidationFailedError)
export class ValidationExceptionFilter implements ExceptionFilter {
  view: string
  objectName: string

  constructor(view: string, objectName: string) {
    this.view = view;
    this.objectName = objectName;
  }

  async catch(exception: ValidationFailedError, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const request = ctx.getRequest<Request>();

    response.render(this.view, {
      errors: exception.validationErrors,
      [this.objectName]: exception.target,
      url: request.url,
    });
  }
}
  

Мы также добавляем инициализатор, чтобы мы могли указать, какой вид отображать и каково имя объекта, чтобы мы могли настроить наш фильтр для метода контроллера следующим образом:

   @Post(':postID')
  @UseFilters(new ValidationExceptionFilter('blog-posts/edit', 'blogPost'))
  @Redirect('/blog-posts', 301)
  async update(
    @Param('id') postID: string,
    @Body() editBlogPostDto: EditBlogPostDto,
  ) {
    await this.blogPostsService.update(postID, editBlogPostDto);
  }
  

Надеюсь, это поможет некоторым людям, потому что мне нравится NestJS, но, похоже, документация и руководства гораздо лучше настроены для JSON API, чем для более традиционных CRUD-приложений с полным стеком.