首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有多选择表单更改事件的angular6-json模式-表单问题

带有多选择表单更改事件的angular6-json模式-表单问题
EN

Stack Overflow用户
提问于 2019-09-21 02:09:56
回答 1查看 1.5K关注 0票数 1

当前的多选择实现没有显示<mat-select [formControl]="toppings" multiple>,因为这里类型为‘数组’和'enum‘,它显示’复选框‘。因此,我以以下方式重写了该行为:

代码语言:javascript
复制
myCustomWidgets = {
    submit: NoneComponent,
    checkboxes: CustomMultiSelectComponent 
  };

我已经创建了一个MaterialSelectComponent文件,它是来自'angular6-json-schema-form‘的同一个文件的副本,然后添加了如下所示的自定义小部件。

代码语言:javascript
复制
<json-schema-form loadExternalAssets="true"
                      [schema]="formData?.schema"
                      [form]="formData?.form"
                      framework="material-design"
                      [widgets]="myCustomWidgets"
                      (isValid)="isFormValid($event)"
                      (onChanges)="onFormChange($event)"
                      (onSubmit)="onFormSubmit($event)">
    </json-schema-form>

我有4个元素,一个文本,一个日期,一个单一选择,和一个多选择,如下所示。

代码语言:javascript
复制
    {
    "form": [{
            "type": "section",
            "htmlClass": "row",
            "items": [{
                    "type": "section",
                    "htmlClass": "col-xs-6 item-padding",
                    "items": ["my_text"]
                }, {
                    "type": "section",
                    "htmlClass": "col-xs-6 item-padding",
                    "items": ["my_date"]
                }
            ]
        }, {
            "type": "section",
            "htmlClass": "row",
            "items": [{
                    "type": "section",
                    "htmlClass": "col-xs-6 item-padding",
                    "items": ["my_multi_select"]
                }, {
                    "type": "section",
                    "htmlClass": "col-xs-6 item-padding",
                    "items": ["my_single_select"]
                }
            ]
        }
    ],
    "schema": {
        "schema": "http://json-schema.org/draft-06/schema#",
        "type": "object",
        "title": "Form Details",
        "description": "",
        "properties": {
            "my_multi_select": {
                "titleSource": "my_multi_select",
                "fieldDisplay": "Select More",
                "title": "Select More",
                "type": "array",
                "pattern": null,
                "description": "Multi Select",
                "format": "",
                "required": false,
                "multiple": true,
                "uniqueItems": true,
                "items": {
                    "type": "string",
                    "enum": ["A", "B", "C", "D"]
                },
                "readonly": false
            },
            "my_text": {
                "titleSource": "my_text",
                "fieldDisplay": "My Text",
                "title": "My Text",
                "type": "string",
                "pattern": "",
                "description": "Enter Text",
                "format": "",
                "required": true,
                "readonly": false
            },
            "my_date": {
                "titleSource": "my_date",
                "fieldDisplay": "My Date",
                "title": "My Date",
                "type": "string",
                "pattern": "",
                "description": "Enter Date",
                "format": "date",
                "required": true,
                "readonly": false
            },
            "my_single_select": {
                "titleSource": "my_single_select",
                "fieldDisplay": "My Single Select",
                "title": "My Single Select",
                "type": "string",
                "pattern": "",
                "description": "Enter Date",
                "format": "date",
                "required": true,
                "readonly": false,
                "enum": [
                    "One",
                    "Two",
                    "Three",
                    "Four"
                ]
            }
        },
        "required": ["my_text", "my_date", "my_single_select"]
    },
    "data": {
        "my_text": "",
        "my_date": "",
        "my_single_select": "",
        "my_multi_select" : []
    }
}

现在的问题是,它不是只为"my_multi_select“元素捕获方法form- issue p.function s.ts文件中的数据更改事件。对于这3个元素的其余部分,任何更改都会得到回调,并捕获值。在这里,我已经在json-schema.form.services.ts下面进行了调试,在这里,所有控件都要注册订阅。在我的4个元素中,多选择是"FormArray“类型,rest是"FormControl”类型。

代码语言:javascript
复制
buildFormGroup() {
    this.formGroup = <FormGroup>buildFormGroup(this.formGroupTemplate);
    if (this.formGroup) {
      this.compileAjvSchema();
      this.validateData(this.formGroup.value);

      // Set up observables to emit data and validation info when form data changes
      if (this.formValueSubscription) { this.formValueSubscription.unsubscribe(); }
      this.formValueSubscription = this.formGroup.valueChanges
        .subscribe(formValue => this.validateData(formValue));
    }
  }

是否存在FormArray类型订阅或事件发射器的已知错误?

我也尝试过使用ViewChild来获取值,但除了Multi-Select之外,我仍然只得到其他人的值。我仍然不明白,在UI中,当我选择多个值时,它仍然显示在其中,这意味着它存储在某个地方(可能在controlValue中),但是为什么没有方法访问该值(如果没有onchange事件)?

代码语言:javascript
复制
<json-schema-form #myJsonSchema
                          loadExternalAssets="true"
                          [schema]="formData?.schema"
                          [form]="formData?.form"
                          framework="material-design"
                          [widgets]="myCustomWidgets"
                          (isValid)="isFormValid($event)"
                          (onChanges)="onFormChange($event)"
                          (onSubmit)="onFormSubmit($event)">
        </json-schema-form>
EN

回答 1

Stack Overflow用户

发布于 2019-10-16 17:53:14

我团队的一个家伙解决了这个问题。请参阅下面的组件代码。基本上,这里使用复选框代码来发出值。为此使用了selectionChange()方法,如代码所示。我们还面临着数据绑定的另一个问题,我们已经修复了它,添加了

代码语言:javascript
复制
import {AbstractControl} from '@angular/forms';
import {buildTitleMap, isArray, JsonSchemaFormService} from 'angular6-json-schema-form';
import {Component, Inject, Input, OnInit, Optional} from '@angular/core';
import {MAT_LABEL_GLOBAL_OPTIONS} from '@angular/material/core';
import {MAT_FORM_FIELD_DEFAULT_OPTIONS} from '@angular/material/form-field';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'material-select-widget',
  template: `
    <mat-form-field
      [appearance]="options?.appearance || matFormFieldDefaultOptions?.appearance || 'standard'"
      [class]="options?.htmlClass || ''"
      [floatLabel]="options?.floatLabel || matLabelGlobalOptions?.float || (options?.notitle ? 'never' : 'auto')"
      [hideRequiredMarker]="options?.hideRequired ? 'true' : 'false'"
      [style.width]="'100%'">
      <mat-label *ngIf="!options?.notitle">{{options?.title}}</mat-label>
      <span matPrefix *ngIf="options?.prefix || options?.fieldAddonLeft"
            [innerHTML]="options?.prefix || options?.fieldAddonLeft"></span>
      <mat-select *ngIf="boundControl"
                  [attr.aria-describedby]="'control' + layoutNode?._id + 'Status'"
                  [attr.name]="controlName"
                  [id]="'control' + layoutNode?._id"
                  [multiple]="options?.multiple"
                  [placeholder]="options?.notitle ? options?.placeholder : options?.title"
                  [required]="options?.required"
                  [style.width]="'100%'"
                  [(value)]="selectedValues"
                  (selectionChange)="selectionChange($event)"
                  (blur)="options.showErrors = true">
        <ng-template ngFor let-selectItem [ngForOf]="selectList">
          <mat-option *ngIf="!isArray(selectItem?.items)"
                      [value]="selectItem?.value">
            <span [innerHTML]="selectItem?.name"></span>
          </mat-option>
          <mat-optgroup *ngIf="isArray(selectItem?.items)"
                        [label]="selectItem?.group">
            <mat-option *ngFor="let subItem of selectItem.items"
                        [value]="subItem?.value">
              <span [innerHTML]="subItem?.name"></span>
            </mat-option>
          </mat-optgroup>
        </ng-template>
      </mat-select>
      <mat-select *ngIf="!boundControl"
                  [attr.aria-describedby]="'control' + layoutNode?._id + 'Status'"
                  [attr.name]="controlName"
                  [disabled]="controlDisabled || options?.readonly"
                  [id]="'control' + layoutNode?._id"
                  [multiple]="options?.multiple"
                  [placeholder]="options?.notitle ? options?.placeholder : options?.title"
                  [required]="options?.required"
                  [style.width]="'100%'"
                  [value]="controlValue"
                  (blur)="options.showErrors = true"
                  (selectionChange)="selectionChange($event)">
        <ng-template ngFor let-selectItem [ngForOf]="selectList">
          <mat-option *ngIf="!isArray(selectItem?.items)"
                      [attr.selected]="selectItem?.value === controlValue"
                      [value]="selectItem?.value">
            <span [innerHTML]="selectItem?.name"></span>
          </mat-option>
          <mat-optgroup *ngIf="isArray(selectItem?.items)"
                        [label]="selectItem?.group">
            <mat-option *ngFor="let subItem of selectItem.items"
                        [attr.selected]="subItem?.value === controlValue"
                        [value]="subItem?.value">
              <span [innerHTML]="subItem?.name"></span>
            </mat-option>
          </mat-optgroup>
        </ng-template>
      </mat-select>
      <span matSuffix *ngIf="options?.suffix || options?.fieldAddonRight"
            [innerHTML]="options?.suffix || options?.fieldAddonRight"></span>
      <mat-hint *ngIf="options?.description && (!options?.showErrors || !options?.errorMessage)"
                align="end" [innerHTML]="options?.description"></mat-hint>
    </mat-form-field>
    <mat-error *ngIf="options?.showErrors && options?.errorMessage"
               [innerHTML]="options?.errorMessage"></mat-error>`,
  styles: [`
    mat-error {
      font-size: 75%;
      margin-top: -1rem;
      margin-bottom: 0.5rem;
    }

    ::ng-deep json-schema-form mat-form-field .mat-form-field-wrapper .mat-form-field-flex
    .mat-form-field-infix {
      width: initial;
    }
  `],
})
export class CustomMultiSelectComponent implements OnInit {
  formControl: AbstractControl;
  controlName: string;
  controlValue: any;
  controlDisabled = false;
  boundControl = false;
  options: any;
  selectList: any[] = [];
  isArray = isArray;
  @Input() layoutNode: any;
  @Input() layoutIndex: number[];
  @Input() dataIndex: number[];

  selectedValues = []

  constructor(
    @Inject(MAT_FORM_FIELD_DEFAULT_OPTIONS) @Optional() public matFormFieldDefaultOptions,
    @Inject(MAT_LABEL_GLOBAL_OPTIONS) @Optional() public matLabelGlobalOptions,
    private jsf: JsonSchemaFormService
  ) {
  }

  ngOnInit() {
    this.options = this.layoutNode.options || {};

    this.selectList = buildTitleMap(
      this.options.titleMap || this.options.enumNames,
      this.options.enum, !!this.options.required, !!this.options.flatList
    );

    this.jsf.initializeControl(this, !this.options.readonly);
    if (!this.options.notitle && !this.options.description && this.options.placeholder) {
      this.options.description = this.options.placeholder;
    }
    if (this.boundControl) {
      const formArray = this.jsf.getFormControl(this);
      for (const selectItem of this.selectList) {
        selectItem.checked = formArray.value.includes(selectItem.value);
      }
    }

    this.selectedValues = this.selectList.filter(item => item.checked)
                                         .map(item => item.value);
  }

  selectionChange(event) {
    this.options.showErrors = true;
    this.selectList.map(item => item.checked = this.selectedValues.includes(item.value));
    if (this.boundControl) {
      this.jsf.updateArrayCheckboxList(this, this.selectList);
    }
  }

}

希望这能帮到你们。任何人都可以使用这段代码。我将在angular6-json模式-表单项目中添加一个PR。

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

https://stackoverflow.com/questions/58036755

复制
相关文章

相似问题

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