【问题标题】:Get value from all checked checkbox in angular从角度中所有选中的复选框中获取值
【发布时间】:2020-08-30 03:37:10
【问题描述】:

我正在使用 Angular 创建测验应用程序,并且我有这样的代码

  ngOnInit() {
    this.myForm = this.fb.group({
      lessonCode: "test",
      answer: this.fb.array([])
    });
  }
  
  onChange(email: string, code: string, isChecked: boolean) {
    const emailFormArray = <FormArray>this.myForm.controls.answer;

    if (isChecked) {
      let array = new FormGroup({
        questionCode: new FormControl(email),
        emailCode: new FormArray([
          new FormControl(code)
        ]),
      });
      emailFormArray.push(array);
    } else {
      let index = emailFormArray.controls.findIndex(x => x.value == email);
      emailFormArray.removeAt(index);
    }
  }

产生这样的数组

Form values: {
  "lessonCode": "test",
  "answer": [
    {
      "questionCode": "pertanyaan2",
      "emailCode": [
        "option2"
      ]
    },
    {
      "questionCode": "pertanyaan2",
      "emailCode": [
        "option1"
      ]
    }
  ]
}

但我真正需要的是这样的

Form values: {
  "lessonCode": "test",
  "answer": [
    {
      "questionCode": "pertanyaan2",
      "emailCode": {
        "option2",
        "option1"
      }
    }
  ]
}

我怎样才能做到这一点?任何想法都会很有帮助

我在这里复制最少https://stackblitz.com/edit/angular-ca1jin?file=src%2Fapp%2Fapp.component.ts

【问题讨论】:

  • emailCode 属性在您的预期结果中不是有效对象。

标签: json angular angular-reactive-forms


【解决方案1】:

我建议了另一种方法

如果我们像这样创建一个formGroup

this.myForm = this.fb.group({
  lessonCode: "test",
  answer: this.fb.array(this.users.map(x=>this.fb.group({
      questionCode:x.code,
      email:[[]]        
  })))
});

看到答案是FormGroup的FormArray,每个FormGroup有两个FormsControl,questionCode和email,那仍然是FormControl(但存储了一个数组)。您不必对 FormArray 感到困惑。 FormControl 可以存储数组、对象、字符串、数字等。存储数组并不奇怪,例如mat-select multiple 也存储一个数组

与往常一样,我们使用 formArrays,我们在 .html 中声明一个要管理的 getter

  get answers()
  {
    return this.myForm.get('answer') as FormArray
  }

嗯,表格有点复杂

<form [formGroup]="myForm">
  <div formArrayName="answer">
    <div *ngFor="let group of answers.controls;let i=index">
        <p>{{users[i].code}}</p>
        <div *ngFor="let user of users[i].email">
            <input #check type="checkbox" 
      [value]="answers.at(i).value.email.indexOf(user.code)>=0"
      (change)="onChange(i,user.code,check.checked)" >{{user.code}}<br>
      </div>
        </div>
  </div>
</form>

看看我们如何使用[value]="answers.at(i).value.email.indexOf(user.code)&gt;=0" 如果我们的“email”控件一开始是空的,这不是必需的,但我们可能希望将来使用这种形式来显示结果,并且我们的“eamil”可以赋值,例如“[选项1]”

要考虑的另一件事是我使用模板引用变量 #check 并发送到函数 OnChange check.checked - 所以我们在函数中收到了一个布尔值-

我们的函数 OnChange 变得更简单了

  onChange(index:number, code: string, isChecked: boolean) {
    const control=this.answers.at(index).get('email')

    if (isChecked && control.value.indexOf(code)<0)
       control.setValue([...control.value,code]
       .sort((a:string,b:string)=>
          this.users[index].email.findIndex(x=>x.code==a)>
          this.users[index].email.findIndex(x=>x.code==b)?1:-1)
       )

    if (!isChecked && control.value.indexOf(code)>=0)
       control.setValue(control.value.filter(x=>x!=code))
  }

我喜欢在删除/添加元素之前检查是否存在

当检查为真时,我们需要“排序”响应 - 否则我们收到响应,例如[option2,option1] - 如果我们的要求不需要,我们可以删除排序-

The stackblitz

【讨论】:

  • 在问题之后,naoval 似乎希望将选项作为表单控件而不是作为值,在您的情况下,您只将每个选项作为值。
  • 我无言以对,这超出了我的知识 xD 真的很有帮助,但如果有人找到这篇文章并阅读你的解决方案,我可以从中学习,非常感谢
  • 其实我并不关心是formcontrol还是value,只要得到相同的结果就可以了
  • 但是就像我说的,也许有一天有人会从你们两个那里找到解决方案,他们可以选择最适合他们需要的解决方案:)
  • @naoval 最后你需要的只是一个选中了你的选项的 json 吗?如果是的话,我们的两个解决方案毫无意义:/你可以有一个初始的 json 并且可以选择是否选中它
【解决方案2】:

你需要做的是将emailCode添加为FormArray而不是FormControl,这样你就可以检查questionCode是否已经存在,如果是,你可以追加到@987654326 @你选中的选项。

唯一需要改变的是你的 onChange 方法

首先你array变量,你需要添加FormArray而不是FormControl

let array = new FormGroup({
  questionCode: new FormControl(email),
  emailCode: new FormArray([])
});

然后为您选中的选项创建一个FormControl

let codeOption = new FormControl(code)

最后,在您的 if 条件中,检查 questionCode 是否已经存在,以便将您的 formControl 附加到它,或创建一个新对象。

if (isChecked) {
  if (emailFormArray.controls.some(obj => obj.get('questionCode').value == email)){
    (<FormArray>emailFormArray.controls.find(obj => obj.get('questionCode').value == email).get('emailCode')).push(codeOption);
  }else{
    (<FormArray>array.get('emailCode')).push(codeOption)
    emailFormArray.push(array)
  }
}

为了更清楚,我已经修改了您的 stackblitz 以满足您的需求

我没有修改else 条件以删除FormArray 上的选项,但您只需复制if 条件即可获取FormArray 的@987654341 上code 元素的索引@。

【讨论】:

  • 这正是我所需要的,非常感谢,所以我只需要弄清楚如何从数组中删除未选中的选项吗?
  • 是的,你只需要像以前一样,在你的 emailCode formarray 中获取代码的索引
  • 好的,我会尝试,希望你能再次帮助我,如果我有任何问题,我会发布,谢谢大佬
  • 抱歉,您说要复制if 条件,我应该复制哪个if 条件?
  • 我已经修改了 stackblitz,现在您可以正确地从您的对象中删除选项
【解决方案3】:

您可以创建一个遍历每个答案并返回所需架构中的对象的函数。

【讨论】:

  • 我不明白,你能解释一下吗?
猜你喜欢
  • 2015-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-18
  • 2011-07-08
  • 1970-01-01
  • 2017-04-03
  • 2017-08-27
相关资源
最近更新 更多