当前的多选择实现没有显示<mat-select [formControl]="toppings" multiple>,因为这里类型为‘数组’和'enum‘,它显示’复选框‘。因此,我以以下方式重写了该行为:
myCustomWidgets = {
submit: NoneComponent,
checkboxes: CustomMultiSelectComponent
};我已经创建了一个MaterialSelectComponent文件,它是来自'angular6-json-schema-form‘的同一个文件的副本,然后添加了如下所示的自定义小部件。
<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个元素,一个文本,一个日期,一个单一选择,和一个多选择,如下所示。
{
"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”类型。
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事件)?
<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>发布于 2019-10-16 17:53:14
我团队的一个家伙解决了这个问题。请参阅下面的组件代码。基本上,这里使用复选框代码来发出值。为此使用了selectionChange()方法,如代码所示。我们还面临着数据绑定的另一个问题,我们已经修复了它,添加了值。
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。
https://stackoverflow.com/questions/58036755
复制相似问题