'How to pass default parameters to the @Query class in Nest.Js?
I'm trying to pass the default parameters maxnodes=3 and addstats=false to the controller via the @Query parameter in Nest.Js.
The code works fine, but the default parameters are not used. When I pass on the query parameters the ones that are passed are shown, but if none are passed, the default values (3 and false) are not used.
How to fix that?
context.contructor.ts:
import { CreateContextQuery } from './context.query';
import { CreateContextDto } from './context.dto';
@Post('graph')
public async createGraphForContext(
@Body('context') contextData: CreateContextDto,
@Query()
contextQuery: CreateContextQuery,
) {
const before = Date.now();
const { context } = await this.contextService.createContext(contextData);
const graph = await this.contextService.getGraphOfContext(
context.id,
contextQuery.maxnodes,
contextQuery.addstats,
);
}
context.query.ts:
import { ApiProperty } from '@nestjs/swagger';
export class CreateContextQuery {
@ApiProperty({
description: 'Maximum number of nodes to show on the graph',
})
maxnodes;
@ApiProperty({
description: 'Include graph statistics',
})
addstats;
constructor(maxnodes = 3, addstats = false) {
this.maxnodes = maxnodes;
this.addstats = addstats;
}
}
Solution 1:[1]
What you receive in the query param is a plain object. You can achieve what you want putting a pipe in your query param and applying a class transform to instantiate the class.
Solution 2:[2]
Read this: https://docs.nestjs.com/pipes#providing-defaults
contextQuery isn't an instance of CreateContextQuery because, without any configuration, Nest won't call new CreateContextQuery any time. This is why you end up using pipes (read this https://docs.nestjs.com/techniques/validation#transform-payload-objects)
Solution 3:[3]
So basically in your DTO, you can give default values.
export class CreateContextQuery {
@IsOptional()
@Type(() => Number)
@IsNumber()
@Min(0)
maxnodes?: number = 3;
@IsOptional()
@Type(() => Boolean)
@IsBoolean()
addstats?: boolean = false;
constructor(maxnodes = 3, addstats = false) {
this.maxnodes = maxnodes;
this.addstats = addstats;
}
}
// as you can see i am using validation too
And in your controller :
@Post('graph')
@UsePipes(new ValidationPipe({ transform: true }))
// you need to add this for tansformation
public async createGraphForContext(
@Body('context') contextData: CreateContextDto,
@Query()
contextQuery: CreateContextQuery,
) {
const before = Date.now();
const { context } = await this.contextService.createContext(contextData);
const graph = await this.contextService.getGraphOfContext(
context.id,
contextQuery.maxnodes,
contextQuery.addstats,
);
}
PS
Also if you want you can add custom decorators, in your case: // add this decorator
export const GetContextQuery = createParamDecorator((_data: unknown, ctx: ExecutionContext): CreateContextDto => {
const request = ctx.switchToHttp().getRequest();
const query = request.query;
const maxnodes = parseInt(query.maxnodes) || 3;//default values here in case it fails to parse
const addstats = Boolean(query.addstats) || 0;
return { addstats, addstats };
});
and in your controller, you can call the decorator instead of @Query
just add your decorator @GetContextQuery() context: CreateContextDto, and now you do not need the UsePipes
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Lazt Omen |
| Solution 2 | Micael Levi |
| Solution 3 |
