nest-validation-view
v0.2.5
Published
NestJS exception filter and decorator for rendering validation errors back to server-side views.
Maintainers
Readme
nest-validation-view
Filtro e decorator para aplicações NestJS que usam views server-side e precisam renderizar erros de validação de volta no formulário.
Instalação
npm install nest-validation-viewUso
Configure o ValidationPipe para usar o payload de erros do pacote:
import { BadRequestException, ValidationPipe } from '@nestjs/common';
import { buildValidationErrorPayload } from 'nest-validation-view';
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
transform: true,
exceptionFactory: (errors) =>
new BadRequestException(buildValidationErrorPayload(errors)),
}),
);Use o decorator no controller. No POST de criação, a view volta para o formulário de cadastro com os dados enviados:
import { Body, Controller, Post } from '@nestjs/common';
import { ValidationView, toBoolean } from 'nest-validation-view';
@Controller('produtos')
export class ProdutoController {
@Post()
@ValidationView('produto/criar', ({ request, errors }) => ({
produto: {
...request.body,
ativo: toBoolean(request.body.ativo, true),
},
errors,
}))
create(@Body() body: unknown) {
return body;
}
}No POST de atualização, use a mesma ideia para voltar para a view de edição. Se a rota tiver :id, repasse o id para a view junto com os dados do formulário:
import { Body, Controller, Param, Post } from '@nestjs/common';
import { ValidationView, toBoolean } from 'nest-validation-view';
@Controller('produtos')
export class ProdutoController {
@Post(':id')
@ValidationView('produto/editar', ({ request, errors }) => ({
produto: {
id: request.params.id,
...request.body,
ativo: toBoolean(request.body.ativo, false),
},
errors,
}))
update(@Param('id') id: string, @Body() body: unknown) {
return { id, ...body };
}
}Para usar o helper nas views, registre validationErrorsHelper nos locals do Express. Assim a view pode chamar validationErrors(locals.errors) sem quebrar quando ainda não houver erros:
import { type Application } from 'express';
import {
type ValidationErrorsViewModel,
validationErrorsHelper,
} from 'nest-validation-view';
type ViewHelpers = {
validationErrors: (
errors: ValidationErrorsViewModel | null | undefined,
) => ValidationErrorsViewModel;
};
export const registerHelpers = (app: Application): void => {
const helpers: ViewHelpers = {
validationErrors: validationErrorsHelper,
};
Object.assign(app.locals, helpers);
};Depois chame esse registro na inicialização da aplicação:
const expressApp = app.getHttpAdapter().getInstance();
registerHelpers(expressApp);Formas de usar errors na view
Em uma view EJS, normalize os erros uma vez no inicio do arquivo. Todos os exemplos abaixo partem dessa variável:
<% const erros = validationErrors(locals.errors); %>Esse objeto sempre tem o mesmo formato, mesmo quando não houver erros:
type ValidationErrorsViewModel = {
all: string[];
fields: Record<string, string[]>;
get: (field: string) => string[];
first: (field: string) => string | null;
has: (field: string) => boolean;
};Resumo com todos os erros usando erros.all:
<% if (erros.all.length) { %>
<div class="alert alert-danger">
<h5>Nao foi possivel salvar.</h5>
<ul>
<% erros.all.forEach((mensagem) => { %>
<li><%= mensagem %></li>
<% }) %>
</ul>
</div>
<% } %>Campo com classe de erro usando erros.has('campo'):
<input
type="text"
name="nome"
class="form-control <%= erros.has('nome') ? 'is-invalid' : '' %>"
value="<%= locals.formData?.nome || '' %>"
>Primeira mensagem de um campo usando erros.first('campo'):
<% if (erros.has('nome')) { %>
<div class="invalid-feedback d-block">
<%= erros.first('nome') %>
</div>
<% } %>Todas as mensagens de um campo usando erros.get('campo'):
<% erros.get('preco').forEach((mensagem) => { %>
<div class="invalid-feedback d-block">
<%= mensagem %>
</div>
<% }) %>Todos os campos que possuem erro usando erros.fields:
<% Object.entries(erros.fields).forEach(([campo, mensagens]) => { %>
<strong><%= campo %></strong>
<ul>
<% mensagens.forEach((mensagem) => { %>
<li><%= mensagem %></li>
<% }) %>
</ul>
<% }) %>Campos aninhados usam o caminho completo gerado pela validação:
<% if (erros.has('endereco.cep')) { %>
<div class="invalid-feedback d-block">
<%= erros.first('endereco.cep') %>
</div>
<% } %>Se quiser importar apenas tipos, use o subpath types:
import type {
ValidationErrorsViewModel,
ValidationFieldErrors,
ValidationViewMetadata,
} from 'nest-validation-view/types';Também é possível importar módulos específicos quando quiser reduzir a superfície do import:
import { buildValidationErrorPayload } from 'nest-validation-view/validation-errors';
import { validationErrorsHelper } from 'nest-validation-view/validation-errors.helper';
import { ValidationView } from 'nest-validation-view/validation-view.decorator';
import { ValidationViewFilter } from 'nest-validation-view/validation-view.filter';API
ValidationView(view, data?, statusCode?): adiciona metadados para o filtro renderizar a view quando houverBadRequestException.ValidationViewFilter: filtro NestJS usado internamente pelo decorator para capturar erros de validação e renderizar a view configurada.buildValidationErrorPayload(errors): converteValidationError[]em{ message, fieldErrors }.validationErrorsHelper(errors): garante um objeto de erros seguro para uso nas views, mesmo quandoerrorsfornullouundefined.toBoolean(value, defaultValue): normaliza valores comuns de formulário comotrue,"true"e"on".
Changelog
0.2.5 - 06/05/2026
- Reorganizada a documentação de uso de
errorsnas views. - Removida a seção de publicação do README para evitar confusão no uso do pacote.
- Documentados exemplos mais claros para
erros.all,erros.has,erros.first,erros.get,erros.fieldse campos aninhados.
0.2.4 - 06/05/2026
- Adicionado exemplo de registro do
validationErrorsHelpernoslocalsdo Express. - Adicionado exemplo de uso do helper em views EJS com
validationErrors(locals.errors). - Documentado o fluxo de inicialização com
registerHelpers(expressApp).
0.2.3 - 06/05/2026
- Adicionado o novo módulo
validation-errors.helper. - Exportados
validationErrorsHelper,ensureValidationErrorsViewModel,createEmptyValidationErrorsViewModele seus tipos pelo import principal do pacote. - Adicionado o subpath
nest-validation-view/validation-errors.helperpara importação direta do helper. - Atualizado o
typesVersionspara resolver os tipos do novo helper no TypeScript. - Melhorado o
buildValidationErrorPayloadpara mesclar mensagens repetidas por campo e evitar mensagens duplicadas no arraymessage. - Documentado o novo helper nos exemplos de importação e na API.
