How to pass default parameters to the @Query class in Nest.Js?

Viewed 3109

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;
  }
}

3 Answers

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

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.

Related