反应式形式正确地将表单值转换为模型对象



在创建模型驱动的模板反应式形式时,当我从形式值创建模型对象时。然后模型对象正在丢失其类型。

对于一个简单的示例:

模型课程:

export class Book {
  public name: string;
  public isbn: string;
}

组件:

@Component({
  selector: 'app-book',
  templateUrl: './book.component.html',
  styleUrls: ['./book.component.css']
})
export class BookComponent implements OnInit {
  bookFormGroup: FormGroup;
  private newBook: Book = new Book();
  constructor(private fb: FormBuilder) {
    this.bookFormGroup = this.fb.group({
      name: new FormControl(''),
      isbn: new FormControl('')
    });
  }
  ngOnInit() {
  }
  addBook() {
    console.log('submit');
    this.newBook = <Book> this.bookFormGroup.value;
    console.log(this.newBook instanceof Book);
    console.log(this.newBook);
  }
}

html:

<form [formGroup]="bookFormGroup" (ngSubmit)="addBook()">
    <input type="text" formControlName="name" >
    <input type="text" formControlName="isbn" >
    <input type="submit" value="Submit">
</form>

在上面的示例中,填充newBook实例后,其转换为普通Object

即,在this.newBook = <Book> this.bookFormGroup.value;

之后

this.newBook instanceof Book正在成为 FALSE

我如何防止这种情况?还是有更好的方法来实现这一目标?

注意:我尝试了JSON.parse(),但它仍然相同。

此构造函数将与任何类型一起使用,并将分配任何匹配。

export class Book {
  public constructor(init?: Partial<Book>) {
        Object.assign(this, init);
    }
}

因此,您将能够做到这一点:

this.newBook = new Book(this.bookFormGroup.value);

,如果书籍课程将来会有任何变化并变得更大。

,这将为您节省很多工作。

我使用传播操作员:

this.newBook = {...this.newBook,...this.bookFormGroup.value}

假设您的模型是这样的:

export class Content {
    ID: number;
    Title: string;
    Summary: string;
}

您的组件看起来像这样:

export class ContentComponent implements OnInit {

  content: Content;
  contentForm: FormGroup;
  ngOnInit() {

    this.contentForm = this.formBuilder.group({
      Title: ['', Validators.required],
      Summary: ['', Validators.required]
    });.....

当调用保存按钮时,您可以合并表单构建器对象和DTO:

oncontentformsubmit(({

// stop here if form is invalid
if (this.contentForm.invalid) {
  return;
}
this.content = Object.assign(this.content, this.contentForm.value);

}

this.content将具有您从OnInit的预定义值和来自组的值。

  1. 您应该有一个接口和一个类,并且类应实现接口。

  2. 用空构造函数创建一个空书。

    export class Book implements IBook {
      constructor(public name = '', public isbn = '') {}
    }
    
  3. 创建一个真实的模型驱动形式。

    this.bookFormGroup = this.fb.group(new Book());
    
  4. 正确键入您的表格

    this.newBook: IBook = this.bookFormGroup.value;
    
let formData = this.formGroup.value as DataModel;

您可以在 addBook()中尝试一下:

 let formData = Object.assign({});
 formData = Object.assign(formData, this.bookFormGroup.value);
 this.newBook = new Book(formData.name ,formData.isbn );
 console.log(this.newBook instanceof Book);

将您的类定义更改为

export class Book {
  constructor(public name: string, public isbn: string) {}
}

将您的addBook方法更改为

addBook() {
  const { name, isbn } = this.bookFormGroup.value;
  this.newBook = new Book(name, isbn);
  console.log(this.newBook instanceof Book);
  console.log(this.newBook);
}

我用这样的静态方法创建了一个辅助类:

export class ObjectAssigner {
  static create<T>(init: Partial<T>): T {
    const value = {};
    Object.assign(value, init);
    return value as T;
  }

以这种方式,我可以将其用于类和类似的接口:

const bookModel= ObjectAssigner.create<Book>(this.bookFormGroup.value);

我已经使用'partical class'来通过类的constractor注入值。当您的表单调用API和模型无需铸造或从反应性形式值创建新的实例时,就可以使用此方法。

export class Address  {
  postCode: string;
  line1: string;
  line2: string;
  county: string;
  city: string;
  country: string;
  cityId: string;
  countryId: string;
  constructor(initialValues: Partial<Address> = {}) {
    if (initialValues) {
      for (const key in initialValues) {
        if (initialValues.hasOwnProperty(key)) {
           this[key] = initialValues[key];
        }
      }
    }
  }
}

我遇到了这个问题,并直接创建formGroup以模型解决了问题。在您的代码中:

  this.bookFormGroup = this.fb.group(Book);

书是您的模型的班级名称。

i使用:

this.formGroupSubscription = this.formGroup.valueChanges.subscribe(form => {
    let mappedObject: MyCreateDTO = form;
    // do stuff with mappedObject.myproperty
});

最新更新