angular - 如何使用 Angular 8 中的 react 形式将模型绑定(bind)到形成构建器

标签 angular angular-reactive-forms reactive

我在我的应用程序中使用了响应式表单,并使用 formcontrolName 绑定(bind)到 html。但是现在我不需要在 formbuilder 中声明属性,而是需要调用一个模型并将该模型分配给 formbuilder 并在 html 中使用它。 我浏览了很多链接,但没有找到任何地方如何根据我的要求工作。

HTML:

<div class="tab-pane fade h-100 active show" id="tab-user_1" role="tabpanel" aria-labelledby="user_1"
    *ngIf="userInfoForm" [formGroup]="userInfoForm">
    <div class="row">
      <div class="col-6">
        <div class="form-group">
          <label for="">Agent Code <span class="text-danger">*</span></label>
          <input type="text" formControlName="agentCode" class="form-control">
        </div>
      </div>
</div>

TS:

 this.userInfoForm = this.FB.group({
        Id: 0,
        agentCode: this.agentCode,
        userName: [''],
        firstName: [''],
        middleName: '',
        lastName: [''],
        department: [''],
      });
      this.userInfoForm.controls['agentCode'].disable();

模型.ts:

export class UserFormDetails {
   Id: number;
   agentCode: number;
   userName: string;
   firstName: string;
   middleName: string;
   lastName: string;
   department: string;
}

DEMO

最佳答案

根据评论,听起来您想要一个基于模型的动态表单……没有“开箱即用”的解决方案可以做到这一点。您可以编写自己的表单模型:

interface MyFormModelField {
  initial?: {
    value: any,
    disabled: boolean
  },
  controlOptions?: AbstractControlOptions
  // anything you find useful really?
}

export type MyFormModel<T> = Record<keyof T, MyFormModelField>

然后像这样实现它:

const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
    Id: { },
    agentCode: {
        initial: {
          value: '',
          disabled: true
        },
        controlOptions: {
          validators: Validators.required
        }
    },
    userName: { },
    firstName: { },
    middleName: { },
    lastName: { },
    department: { },
}

然后您可以编写一个服务来根据表单模型的实例生成表单组...

@Injectable({providedIn: 'root'})
export class MyFormBuilder {
  constructor(private: fb) { }

  buildForm<T>(formModel: MyFormModel<T>) {
    const fg = Object.keys(formModel).reduce((grp, k) => {
      const fld = formModel[k];
      return Object.assign(grp, {
        [k]: [fld.initial || '', fld.controlOptions]
      })
    }, {});
    return this.fb.group(fg);
  }
}

现在,无论何时您对 UserFormDetails 界面进行更改,typescript 都会要求您使用字段信息更新相应的表单模型……虽然更新不会“自动”从模型更新,您至少在表单中具有某种类型安全性。我个人会在这里停下来。

下一部分并不完美,我不喜欢它,但如果您真的希望下一步从类定义中或多或少地自动进行,您可以编写一个函数来构建一个来自类的默认表单模型,如下所示:

function buildDefaultFormModel<T>(model: new () => T) {
  return Object.keys(new model()).reduce((form, k) => {
      return Object.assign(form, {[k]: {}})
  }, {} as MyFormModel<T>)
}

这需要两件事,1,您为其构建表单的类必须为每个字段指定一个默认值,没有默认值的字段将不包括在内。 (这引入了对具有默认值的字段的隐藏依赖,这就是为什么我不喜欢这种方法,但是,如果您编写的类具有没有默认值或构造函数分配的属性,您可以配置 ts 对您大喊大叫):

class UserFormDetails {
   Id: number = 0;
   agentCode: number = 0;
   userName: string = '';
   firstName: string = '';
   middleName: string = '';
   lastName: string = '';
   department: string = '';
}

2、对象的构造函数必须不带参数。但是如果你在这种情况下试图滥用它,TS 会冲你大喊大叫。

函数可以这样使用:

const USER_FORM_MODEL: MyFormModel<UserFormDetails> = {
  ...buildDefaultFormModel(UserFormDetails),
  ...{
    agentCode: {
      initial: {
        value: '',
        disabled: true
      },
      controlOptions: {
        validators: Validators.required
      }
    },
  }
}

这样您就可以使用默认字段,还可以为特定字段提供覆盖。

最后,您还可以利用此表单模型来构建模板,但这是一项更大的任务。

这是一个 Blitz ,所有这些都已实现(我继续清理 Controller 代码):https://stackblitz.com/edit/github-ck3u8u-qtnasc?file=src%2Fapp%2Fuser-table%2Fuser-table.validators.ts

关于angular - 如何使用 Angular 8 中的 react 形式将模型绑定(bind)到形成构建器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61657941/

相关文章:

Angular Form Control 导致无限循环

java - Spring WebClient - HTTP 错误状态的自定义响应回调

java - Spring boot MongoDB Change Streams 不起作用

angular - RXJS BehaviorSubject getValue 与值(value)

javascript - 带有凭据的 Angular 6 httpClient Post

javascript - 修复了 ios safari 弹跳时标题消失的问题

angular - Material 图标无法正确呈现

javascript - 如何使用 Validator 和 Control Value Accessor 正确实现嵌套表单?

angular - 更改日期时间选择器输入 react 形式中的时间格式

javascript - 创建一个元史诗,其工作方式类似于combineEpics,但根据 namespace 选择一个史诗