nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
68.18k stars 7.67k forks source link

ValidateNested doesn't work properly #4849

Closed YouNone closed 4 years ago

YouNone commented 4 years ago

Front-end form data

{name: "group name", code: "2222", items: {…}, id: 2} name: "group name" code: "2222" id: 2 items: { added: [1, 2, 3] deleted: Array(0) }

Bug Report

When I'm trying to add array of id's in Group.items.added, the @ValidateNested doesn't show nested fields

Current behavior

HTTP/1.1 500 Internal Server Error

{ "statusCode": 500, "message": "Internal server error" }

Input Code

// update-dto
import { CreateGroupDto } from './create-group.dto';
import { IsInt, ValidateNested} from 'class-validator';
import { Type } from 'class-transformer';

export class ChangeGroupStateDto {
    @ValidateNested({ each: true })
    @Type(() => Number)
    added: number[];

    @ValidateNested({ each: true })
    @Type(() => Number)
    deleted: number[];
}
export class UpdateGroupDto extends CreateGroupDto {
    @IsInt()
    id: number;

    @Type(() => ChangeGroupStateDto)
    @ValidateNested({ each: true })
    public items: ChangeGroupStateDto;

}

//group service 
// this is what I get in incomeData ==> 
// {id: 2, name: "group name", code: "2222", items: Object {} }
async updateGroup(id: number, incomeData: UpdateGroupDto): Promise<Group> {
        incomeData.id = id;
        const group = await this.getGroupById(incomeData.id);
        group.users = group.users.filter((user) => !incomeData.items.deleted.includes(user.id));
        incomeData.items.added.forEach((itemId) => {
            const newItem = new User();
            newItem.id = itemId;
            group.users.push(newItem);
        });
        console.log(group);
        return await this.repo.save(group);
    }

// group entity
import { IGroup } from './../share/type';
import { User } from './../user/user.entity';
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn, ManyToMany, JoinTable } from "typeorm";

@Entity()
export class Group implements IGroup {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column({ nullable: true })
    code?: string;

    @CreateDateColumn()
    date_create?: string;

    @UpdateDateColumn()
    date_modify?: string;

    @ManyToMany(type => User)
    @JoinTable({name: "group_users_user"})
    users: User[];
}

Expected behavior

I'm trying to get this output { "id": 2, "name": "group name", "code": "2222", "items": { "added": [1, 2, 3], "deleted": [] } }

Environment


Nest version:  
    "@nestjs/common": "^7.0.11",
    "@nestjs/core": "^7.0.11",
    "@nestjs/jwt": "^7.0.0",
    "@nestjs/ng-universal": "^3.2.0",
    "@nestjs/passport": "^7.0.0",
    "@nestjs/platform-express": "^7.0.11",
    "@nestjs/typeorm": "^7.1.0",
    "bcryptjs": "^2.4.3",
    "class-transformer": "^0.2.3",
    "class-validator": "^0.11.1",


For Tooling issues:
- Node version: ^13.13.9
- Platform:  Windows

Others:

kamilmysliwiec commented 4 years ago

items is an object, not an array.

Change:

@Type(() => ChangeGroupStateDto)
@ValidateNested({ each: true })
public items: ChangeGroupStateDto;

to:

@Type(() => ChangeGroupStateDto)
@ValidateNested()
public items: ChangeGroupStateDto;

Please, use our Discord channel (support) for such questions. We are using GitHub to track bugs, feature requests, and potential improvements.

YouNone commented 4 years ago

Thanks, works for me!