【问题标题】:Reactive Forms correctly convert Form Value to Model Object反应式表单正确地将表单值转换为模型对象
【发布时间】:2018-10-04 11:36:49
【问题描述】:

在创建模型驱动模板响应式表单时,当我从表单值创建模型对象时。然后模型对象正在失去它的 TYPE。

举个简单的例子:

模型课本:

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 = &lt;Book&gt; this.bookFormGroup.value;之后

this.newBook instanceof Book 正在变成FALSE

如何防止这种情况发生? 或者有没有更好的方法来实现这一点?

注意:我试过JSON.parse(),但还是一样。

【问题讨论】:

标签: angular typescript


【解决方案1】:

此构造函数适用于任何类型,并将分配任何匹配的字段。

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

所以你可以这样做:

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

如果Book类将来有任何变化并变得更大,这将为您节省大量工作。

【讨论】:

  • 嘿,感谢您的回答,当我的 Book 类扩展另一个类时,我如何使它工作??
  • 只需在构造函数中调用空的 super() 即可。父字段也将适用。
  • 喜欢这个!正是我需要的——非常感谢!
【解决方案2】:

我使用扩展运算符:

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

【讨论】:

  • 只使用属性而不是类的功能
  • 您将发布到服务器的表单值不应包含函数。 @HawklmCG
【解决方案3】:

假设你的模型是这样的:

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 获得的预定义值以及来自 from 组的值。

【讨论】:

  • 这很有帮助!非常感谢!! +1
【解决方案4】:
  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;
    

【讨论】:

  • 当我们向 bookFormGroup 传递一个 new Book() 时,如何向它添加验证?
  • 我从未遇到过此案,但有一个official documentation 可能对您有所帮助。如果必须这样做,我将创建一个接受表单组作为参数的类方法,从而可以设置验证器。
【解决方案5】:

你可以在你的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);

【讨论】:

    【解决方案6】:

    将您的类定义更改为

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

    【讨论】:

      【解决方案7】:

      我使用'Partical class'通过类的构造器注入价值。 这可以在您的表单调用 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];
              }
            }
          }
        }
      }
      

      【讨论】:

        【解决方案8】:
        let formData = this.formGroup.value as DataModel;
        

        【讨论】:

          【解决方案9】:

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

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

          Book 是模型的类名。

          【讨论】:

          • 如何处理 FormGroup 验证(即书籍的前端暴露属性)?
          【解决方案10】:

          我用:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-03-30
            • 2016-10-15
            • 2019-04-03
            • 1970-01-01
            • 2012-07-16
            • 2016-06-26
            • 1970-01-01
            相关资源
            最近更新 更多