首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用逻辑复制表单

用逻辑复制表单
EN

Stack Overflow用户
提问于 2020-11-11 16:28:10
回答 1查看 62关注 0票数 0

我已经创建了一个动态表单字段,通过按钮上的回调函数添加和删除该字段,DelBtn()删除项,AddBtn()添加项。

每个表单字段都有一个value输入。

我还有一个totalval字段。我期望所有value字段中的值之和不超过totalval。如果是这样的话,我们将显示一条错误消息,如果值等于,则会显示reason表单字段。

示例:

如果我有totalValue = 100。现在假设我有我的第一个表单字段value = 90

然后我复制表单,在下一个字段中设置value = 10,那么reason字段应该会出现,因为90 + 10 = 100。当到达totalValue reason 时,应出现reason表单字段,并禁用添加按钮

如果在第二次尝试中,如果用户试图输入大于10的值,则应该显示错误消息。

下面是我的当前代码

在我的TS文件里

代码语言:javascript
复制
  ischecks: boolean = true;
  formsArray = [""];
  count: number = 0;
  totalval: number = 100;

  ngOnInit(): void {}
  constructor() {}

  clickCount(): void {
    this.count++;
  }

  DelBtn = delIndex => this.formsArray.splice(delIndex, 1);
  AddBtn = () => this.formsArray.push("");

HTML

代码语言:javascript
复制
<h2> Form</h2>

<pre style="font-weight: bolder;font-family:verdana;margin-left: 35px;">Total Value:{{totalval}}       </pre>
<div *ngFor="let i of formsArray; let a = index">

    <div>
        <form>
            <table>
                <div>
                    <label for="fname">Value:</label><br>
                    <input type="text" id="fname" name="fname" ><br>
                    <tr>
                        <td>
                            <button type="button" class="btn btn-outline-success"
        style="border-radius:40px;margin-left: 50px" (click)="DelBtn(a)" ><span class="fa fa-plus"></span>Delete</button>
                        </td>
                    </tr>
                    <tr>
                </div>
            </table>
        </form>
    </div>
</div>

<div *ngIf=ischecks style="margin-left:35%">
    <label for="fname">Reason:</label><br>
    <input type="text" id="fname" name="fname" ><br>
</div>
    <br>
    <button type="button" class="btn btn-outline-success"
            style="border-radius:40px;margin-left: 50px;margin-bottom: 30%;" (click)="AddBtn()"  ><span class="fa fa-plus"></span>Add</button>

https://stackblitz.com/edit/angular-ivy-3pbdwv?file=src%2Fapp%2Fapp.component.html

注意:如果你不明白这个问题,可以在评论中问我,我正在用角度写(打字稿)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-11 18:37:20

这将很难用基本的Javascript来实现。下面的方法使用ReactiveForm方法

我们遵循以下步骤

  • ReactiveFormsModule添加到模块的imports数组中
代码语言:javascript
复制
@NgModule({
  imports:[ ReactiveFormsModule, ... ],
  • 注入FormBuilder
代码语言:javascript
复制
constructor(private fb: FormBuilder) {}
  • 定义表单
代码语言:javascript
复制
myForm = this.fb.group({
  totalVal: [100],
  formsArray: this.fb.array([this.fb.control("", { validators: [Validators.required] })]),
  reason: ["", [Validators.required]]
}, { validators: [sumMatches] });

我们增加了一个缓冲验证器sumMatches。我们将使用此方法检查总价值之和是否匹配。

代码语言:javascript
复制
function sumMatches(control): ValidationErrors | undefined {
  const totalVal = Number(control.get("totalVal").value);
  const formsArrayTotal = control
    .get("formsArray")
    .value.reduce((a, b) => Number(a) + Number(b), 0);
  if (formsArrayTotal !== totalVal) {
    return {
      sumMismatch: true
    };
  }
  return;
}
  • 接下来,我们定义帮助器getter函数,从formGroup中提取属性。
代码语言:javascript
复制
  get sumMismatch(): boolean {
    return this.myForm.hasError('sumMismatch')
  }
  get arrayFullyFilled() {
    return !this.formsArray.controls.some(item => item.errors)
  }
  get formsArray() {
    return this.myForm.get("formsArray") as FormArray;
  }
  get totalVal() {
    return this.myForm.get("totalVal") as FormControl;
  }
  • 我们还需要修改函数以从formArray中添加和删除项。
代码语言:javascript
复制
  DelBtn = delIndex => this.formsArray.controls.splice(delIndex, 1);
  AddBtn = () => this.formsArray.push(this.fb.control(""));
  • 最后,我们可以在html中实现formGroup
代码语言:javascript
复制
<h2> Form</h2>

<span class='totalVal'>Total Value:{{ totalVal.value }}</span>

<form [formGroup]='myForm'>
    <ng-container formArrayName='formsArray'>
        <table *ngFor="let item of formsArray.controls; let i = index">
            <tr>
                <td>
                    <div>
                        <label [attr.for]="'fname' + i">Value:</label><br>
                        <input type="number" [formControlName]="i" type="text" [id]="'fname' + i" name="fname" ><br>
                </div>
                </td>
                <td>
                    <button type="button" class="btn btn-outline-success"
        s (click)="DelBtn(i)" ><span class="fa fa-plus"></span>Delete</button></td>
            <tr>

        </table>
    </ng-container>
    <div *ngIf='!sumMismatch && arrayFullyFilled'>
        <label for="fname">Reason:</label><br>
        <input type="text" id="fname" name="fname" ><br>
</div>
        <br>
        <button type="button" class="btn btn-outline-success"
       (click)="AddBtn()"  ><span class="fa fa-plus"></span>Add</button>
        <br>
  <span class="error" *ngIf="sumMismatch && myForm.touched">Total Value Mismatch</span>
</form>

我已经将css解压到自己的文件中。

代码语言:javascript
复制
.totalVal {
  font-weight: bolder;
  font-family: verdana;
}
.btn-outline-success {
  border-radius: 40px;
  margin-left: 50px;
}
.error {
  color: red;
}

看这个演示

编辑1-验证器是如何工作的?

为了理解这一点,我们看一下我们如何构建表单组。我们定义了一个在表单中生成值的结构。

代码语言:javascript
复制
  {
    totalVal: 100,
    formsArray: [''],
    reason: ''
  }

通过将表单组定义为this.fb.group({ ... }, {validators: [ sumMatches ] },具有上述值的表单组将传递给sumMatches函数

sumMatches中,我们将有一个类似于具有以下值的formGroup

代码语言:javascript
复制
  {
    totalVal: 100,
    formsArray: ['50', '20', '10'],
    reason: ''
  }

在上面的文章中,我们简单地使用control.get('totalVal').valuecontrol.get('totalVal').value中提取100到formArray。由于formArray值将是一个数组,所以我们可以使用reduce函数对此进行求和。最后,我们对此进行比较,如果匹配则返回null,如果不匹配则返回Object

使用上述方法,角响应表单将根据用户提供的内容更新表单valid状态的值。因此,我们可以利用这个valid状态来更新UI

arrayFullyFilled()

代码语言:javascript
复制
get arrayFullyFilled() { 
  return !this.formsArray.controls.some(item => item.errors) 
}

上面的代码试图找出用户是否已将数组中的输入全部填充。在我们的数组中,我们获取所有控件,检查其中一些控件是否有错误,如果有错误,则返回false,否则返回true。这是可能的,因为在我的formGroup中,我使用Validators.required验证将formControls作为required来实现。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64790312

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档