diff --git a/CONFIG.md b/CONFIG.md index ccb3565..ac37867 100755 --- a/CONFIG.md +++ b/CONFIG.md @@ -281,3 +281,18 @@ Submit a form. // Demo code: ``` + +- change + +Form item value change event + +``` +// Demo code: + + +onChange({paths, itemValue, formValue}) { + // paths: the path of the item whose value changes +  // itemValue: the latest value of the item whose value has changed +  // formVallue: the latest value of the form +} +``` diff --git a/CONFIG_CN.md b/CONFIG_CN.md index 3c75f52..e8fa2ed 100644 --- a/CONFIG_CN.md +++ b/CONFIG_CN.md @@ -282,3 +282,18 @@ const allWidgets = this.$ncformAllWidgets(); // Demo code: ``` + +- change + +表单项值更改事件 + +``` +// Demo code: + + +onChange({paths, itemValue, formValue}) { + // paths: 发生值变化的项的路径 + // itemValue:发生值变化的项的最新值 + // formVallue: 表单的最新值 +} +``` diff --git a/STD-COMP.md b/STD-COMP.md index fdbd004..d0eb993 100755 --- a/STD-COMP.md +++ b/STD-COMP.md @@ -63,7 +63,8 @@ If you don't like the cold text description, click on the [interactive version]( remoteUrl: '', // If it is remote call, fill in the url resField: '', // Response result field }, - modelField: '' // An attribute used to bind the value of the input value + modelField: '', // An attribute used to bind the value of the input value + placeholder: '', // placeholder }, appendSelect: { // Append select, The data used for this kind must be an object itemLabelField: 'label', // Item data represents the field of the label @@ -73,7 +74,8 @@ If you don't like the cold text description, click on the [interactive version]( remoteUrl: '', // If it is remote call, fill in the url resField: '', // Response result field }, - modelField: '' // An attribute used to bind the value of the input value + modelField: '', // An attribute used to bind the value of the input value + placeholder: '', // placeholder } }, @@ -280,6 +282,7 @@ If you don't like the cold text description, click on the [interactive version]( item: '', all: '' }, + showOneIfEmpty: false, // Show one item if empty } ``` @@ -299,6 +302,7 @@ If you don't like the cold text description, click on the [interactive version]( item: '', all: '' }, + showOneIfEmpty: false, // Show one item if empty } ``` @@ -316,5 +320,6 @@ If you don't like the cold text description, click on the [interactive version]( item: '', all: '' }, + showOneIfEmpty: false, // Show one item if empty } ``` diff --git a/STD-COMP_CN.md b/STD-COMP_CN.md index 8a602c4..1856730 100644 --- a/STD-COMP_CN.md +++ b/STD-COMP_CN.md @@ -63,7 +63,8 @@ remoteUrl: '', // 如果是远程访问,则填写该url resField: '', // 响应结果的字段 }, - modelField: '' // 用于绑定input value值的某个属性 + modelField: '', // 用于绑定input value值的某个属性 + placeholder: '', // 占位描述 }, appendSelect: { // 后置下拉框,使用该种的数据必须是对象 itemLabelField: 'label', // 项数据表示label的字段 @@ -73,7 +74,8 @@ remoteUrl: '', // 如果是远程访问,则填写该url resField: '', // 响应结果的字段 }, - modelField: '' // 用于绑定input value值的某个属性 + modelField: '', // 用于绑定input value值的某个属性 + placeholder: '', // 占位描述 } }, @@ -280,6 +282,7 @@ item: '', all: '' }, + showOneIfEmpty: false, // 当空值时是否显示一项 } ``` @@ -299,6 +302,7 @@ item: '', all: '' }, + showOneIfEmpty: false, // 当空值时是否显示一项 } ``` @@ -316,5 +320,6 @@ item: '', all: '' }, + showOneIfEmpty: false, // 当空值时是否显示一项 } ``` diff --git a/packages/ncform-common/src/mixins/vue/layout-array-mixin.js b/packages/ncform-common/src/mixins/vue/layout-array-mixin.js index 8747cdb..0fa739e 100755 --- a/packages/ncform-common/src/mixins/vue/layout-array-mixin.js +++ b/packages/ncform-common/src/mixins/vue/layout-array-mixin.js @@ -17,13 +17,14 @@ export default { this.$options.lang = window.__$ncform.lang; this.$data.i18n = this.$options.i18nData[this.$options.lang] || this.$options.i18nData.en; - this.schema.value = - this.schema.value && this.schema.value.length > 0 - ? this.schema.value - : [ncformUtils.getDefVal(this.schema.items.type)]; - this.schema.value.forEach((item, idx) => { - this.addItem(idx); - }); + this.schema.value = this.schema.value || []; + if (this.schema.value.length === 0) { + this._addEmptyItem(); + } else { + this.schema.value.forEach((item, idx) => { + this.addItem(idx); + }); + } this.$data.collapsed = this.mergeConfig.collapsed; @@ -111,6 +112,12 @@ export default { this.$set(this.tempData, key, value); }, + _addEmptyItem() { + if (this.schema.value.length === 0 && this.mergeConfig.showOneIfEmpty) { + this.$nextTick(() => this.addItem()); + } + }, + isNormalObjSchema: ncformUtils.isNormalObjSchema, isNormalArrSchema: ncformUtils.isNormalArrSchema, @@ -145,15 +152,18 @@ export default { type: 'warning' }).then(() => { this.schema.value.splice(idx, 1); + this._addEmptyItem(); }) } else { this.schema.value.splice(idx, 1); + this._addEmptyItem(); } } else { if (requiredConfirm) { - window.confirm(confirmText) && this.schema.value.splice(idx, 1); + window.confirm(confirmText) && this.schema.value.splice(idx, 1) && this._addEmptyItem(); } else { this.schema.value.splice(idx, 1); + this._addEmptyItem(); } } }, @@ -165,15 +175,18 @@ export default { type: 'warning' }).then(() => { this.schema.value = []; + this._addEmptyItem(); }) } else { this.schema.value = []; + this._addEmptyItem(); } } else { if (requiredConfirm) { - window.confirm(confirmText) && (this.schema.value = []); + window.confirm(confirmText) && (this.schema.value = []) && this._addEmptyItem(); } else { this.schema.value = []; + this._addEmptyItem(); } } diff --git a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/array.spec.js b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/array.spec.js index b0bfdfc..02671b6 100644 --- a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/array.spec.js +++ b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/array.spec.js @@ -76,9 +76,11 @@ context('Array', () => { cy.get('legend').click(); cy.get('legend').next().should('be.visible'); + cy.get('button').contains('Add Item').click(); cy.get('input').should('not.be.visible'); cy.get('button').find('.el-icon-arrow-up').click() cy.get('input').should('be.visible'); + cy.get('input').its('length').should('equal', 1); cy.get('button').contains('Add Item').click(); cy.get('button').find('.el-icon-arrow-up:visible').click() @@ -363,4 +365,57 @@ context('Array', () => { }); }); + it('showOneIfEmpty option', () => { + let formSchema = { + type: 'object', + properties: { + users1: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + }; + cy.window() + .its('editor') + .invoke('setValue', JSON.stringify(formSchema, null, 2)); + common.startRun(); + + cy.get('body').as('body'); + + cy.get('.previewArea').within(() => { + // Declare action elements + cy.get('legend') + .contains('users1') + .parent() + .within(() => { + // 默认有一项 + cy.get('input').its('length').should('equal', 1); + cy.get('input').eq(0).should('have.value', ''); + + // 填写值然后删除该项 + cy.get('input').eq(0).type('daniel'); + cy.get('input').eq(0).should('have.value', 'daniel'); + cy.get('.el-icon-remove').eq(0).click(); + cy.get('input').eq(0).should('have.value', ''); + + // 增加多一项,然后删除全部 + cy.get('button').contains('Add').click(); + cy.get('input').its('length').should('equal', 2); + cy.get('input').eq(0).type('daniel'); + cy.get('input').eq(1).type('sarah'); + cy.get('button:contains("Delete All")').click(); + cy.get('input').its('length').should('equal', 1); + cy.get('input').eq(0).should('have.value', ''); + }); + + // common.submitForm(); + }); + }); }); diff --git a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/input.spec.js b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/input.spec.js index 25e30b8..9dfdfbb 100644 --- a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/input.spec.js +++ b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/input.spec.js @@ -104,7 +104,7 @@ context('input', () => { ui: { widgetConfig: { prefixIcon: 'el-icon-search', - trim: false + trim: true } } }, @@ -142,7 +142,7 @@ context('input', () => { .as('nameInput1'); cy.get('@nameInput1') .type(' daniel ') - .should('have.value', ' daniel '); + .should('have.value', 'daniel'); cy.get('@nameInput1') .parent() .find('.el-icon-search') @@ -165,7 +165,7 @@ context('input', () => { .should('not.be.visible'); cy.get('@nameInput2') .type(' daniel ') - .should('have.value', 'daniel'); + .should('have.value', ' daniel '); cy.get('@nameInput2') .parent() .find('.el-input__clear') diff --git a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/radio.spec.js b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/radio.spec.js index 10e6f96..eea146e 100644 --- a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/radio.spec.js +++ b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/radio.spec.js @@ -205,7 +205,10 @@ context('Radio', () => { type: 'string' }, ui: { - widget: 'array-table' + widget: 'array-table', + widgetConfig: { + showOneIfEmpty: true + } } }, name1: { diff --git a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/table.spec.js b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/table.spec.js index c2fe9e1..e0f6a00 100644 --- a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/table.spec.js +++ b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/table.spec.js @@ -81,6 +81,7 @@ context('Table', () => { cy.get('legend').click(); cy.get('legend').next().should('be.visible'); + cy.get('button').contains('Add Item').click(); cy.get('button').contains('Add Item').click(); cy.get('input').its('length').should('equal', 2); @@ -360,4 +361,59 @@ context('Table', () => { }); }); + it('showOneIfEmpty option', () => { + let formSchema = { + type: 'object', + properties: { + users1: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widget: 'array-table', + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + }; + cy.window() + .its('editor') + .invoke('setValue', JSON.stringify(formSchema, null, 2)); + common.startRun(); + + cy.get('body').as('body'); + + cy.get('.previewArea').within(() => { + // Declare action elements + cy.get('legend') + .contains('users1') + .parent() + .within(() => { + // 默认有一项 + cy.get('input').its('length').should('equal', 1); + cy.get('input').eq(0).should('have.value', ''); + + // 填写值然后删除该项 + cy.get('input').eq(0).type('daniel'); + cy.get('input').eq(0).should('have.value', 'daniel'); + cy.get('.el-icon-remove').eq(0).click(); + cy.get('input').eq(0).should('have.value', ''); + + // 增加多一项,然后删除全部 + cy.get('button').contains('Add').click(); + cy.get('input').its('length').should('equal', 2); + cy.get('input').eq(0).type('daniel'); + cy.get('input').eq(1).type('sarah'); + cy.get('button:contains("Delete All")').click(); + cy.get('input').its('length').should('equal', 1); + cy.get('input').eq(0).should('have.value', ''); + }); + + // common.submitForm(); + }); + }); + }); diff --git a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/tabs.spec.js b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/tabs.spec.js index 4d354ce..c5cfe0e 100644 --- a/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/tabs.spec.js +++ b/packages/ncform-e2e/ncform-theme-elementui/cypress/integration/examples/tabs.spec.js @@ -79,6 +79,7 @@ context('Tabs', () => { cy.get('legend').click(); cy.get('legend').next().should('be.visible'); + cy.get('.el-icon-plus').click(); cy.get('.el-icon-plus').click(); cy.get('.el-tabs__item').its('length').should('equal', 2); cy.get('.el-tabs__item:last-child').should('have.class', 'is-active'); @@ -135,4 +136,50 @@ context('Tabs', () => { }); }); + it('showOneIfEmpty option', () => { + let formSchema = { + type: 'object', + properties: { + users1: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widget: 'array-tabs', + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + }; + cy.window() + .its('editor') + .invoke('setValue', JSON.stringify(formSchema, null, 2)); + common.startRun(); + + cy.get('body').as('body'); + + cy.get('.previewArea').within(() => { + // Declare action elements + cy.get('legend') + .contains('users1') + .parent() + .within(() => { + // 默认有一项 + cy.get('.el-tabs__item').its('length').should('equal', 1); + cy.get('input').should('have.value', ''); + + // 填写值然后删除该项 + cy.get('input').type('daniel'); + cy.get('input').should('have.value', 'daniel'); + cy.get('.el-icon-close').click(); + cy.get('input').should('have.value', ''); + }); + + // common.submitForm(); + }); + }); + }); diff --git a/packages/ncform-e2e/ncform/cypress/integration/examples/customRule.spec.js b/packages/ncform-e2e/ncform/cypress/integration/examples/customRule.spec.js index 97cc550..24b640f 100644 --- a/packages/ncform-e2e/ncform/cypress/integration/examples/customRule.spec.js +++ b/packages/ncform-e2e/ncform/cypress/integration/examples/customRule.spec.js @@ -29,6 +29,8 @@ context('rules.customRule', () => { it('rules.customRule in Array', () => { let id = md5('rules.customRule in Array'); cy.get(`[data-cy=${id}]`).within(() => { + cy.get('legend').contains('rows').parent().find('button').contains('Add').click(); + cy.get('label').contains('maxNum').next().find('input').as('maxNumInput'); cy.get('label').contains('minNum').next().find('input').as('minNumInput'); diff --git a/packages/ncform-theme-elementui/examples/control-comps/input.html b/packages/ncform-theme-elementui/examples/control-comps/input.html index 794b977..874c2cd 100755 --- a/packages/ncform-theme-elementui/examples/control-comps/input.html +++ b/packages/ncform-theme-elementui/examples/control-comps/input.html @@ -444,7 +444,8 @@ resField: Which field of the response data as the data source, as the example re itemLabelField: 'label', // 项数据表示label的字段 itemValueField: 'value', // 项数据表示value的字段 enumSource: [{ value: 1, label: 'Man' }, { value: 2, label: 'Woman' }], // 本地数据源 - modelField: 'gender' // 用于绑定input value值的某个属性 + modelField: 'gender', // 用于绑定input value值的某个属性 + placeholder: 'Select', } } } @@ -489,7 +490,8 @@ note: remoteUrl: '/api/input/getDomains', // 如果是远程访问,则填写该url resField: '' // 响应结果的字段 }, - modelField: 'domain' // 用于绑定input value值的某个属性 + modelField: 'domain', // 用于绑定input value值的某个属性 + placeholder: '', } } } diff --git a/packages/ncform-theme-elementui/examples/layout-comps/array-table.html b/packages/ncform-theme-elementui/examples/layout-comps/array-table.html index a396aee..0da1fb4 100755 --- a/packages/ncform-theme-elementui/examples/layout-comps/array-table.html +++ b/packages/ncform-theme-elementui/examples/layout-comps/array-table.html @@ -316,7 +316,31 @@ Prompt information can be configured via delConfirmText when requiredDelConfirm 2. delConfirmText.all: delete all confirmation information          ` } - } + }, + { + title: { + cn: '[属性] showOneIfEmpty: 当空值时是否显示一项', + en: + '[ATTR] showOneIfEmpty: Show one item at least if empty' + }, + schema: { + type: 'object', + properties: { + user: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widget: 'array-table', + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + } + }, ]; // Bootstrap the app diff --git a/packages/ncform-theme-elementui/examples/layout-comps/array-tabs.html b/packages/ncform-theme-elementui/examples/layout-comps/array-tabs.html index 48f42d8..7dae0e2 100755 --- a/packages/ncform-theme-elementui/examples/layout-comps/array-tabs.html +++ b/packages/ncform-theme-elementui/examples/layout-comps/array-tabs.html @@ -273,7 +273,31 @@ Prompt information can be configured via delConfirmText when requiredDelConfirm 1. delConfirmText.item: delete item confirmation information          ` } - } + }, + { + title: { + cn: '[属性] showOneIfEmpty: 当空值时是否显示一项', + en: + '[ATTR] showOneIfEmpty: Show one item at least if empty' + }, + schema: { + type: 'object', + properties: { + user: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widget: 'array-tabs', + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + } + }, ]; // Bootstrap the app diff --git a/packages/ncform-theme-elementui/examples/layout-comps/array.html b/packages/ncform-theme-elementui/examples/layout-comps/array.html index 9766bb2..484f666 100755 --- a/packages/ncform-theme-elementui/examples/layout-comps/array.html +++ b/packages/ncform-theme-elementui/examples/layout-comps/array.html @@ -350,7 +350,30 @@ Prompt information can be configured via delConfirmText when requiredDelConfirm 2. delConfirmText.all: delete all confirmation information          ` } - } + }, + { + title: { + cn: '[属性] showOneIfEmpty: 当空值时是否显示一项', + en: + '[ATTR] showOneIfEmpty: Show one item at least if empty' + }, + schema: { + type: 'object', + properties: { + user: { + type: 'array', + items: { + type: 'string' + }, + ui: { + widgetConfig: { + showOneIfEmpty: true + } + } + } + } + } + }, ]; // Bootstrap the app diff --git a/packages/ncform-theme-elementui/src/components/control-comps/input.vue b/packages/ncform-theme-elementui/src/components/control-comps/input.vue index f84c3f3..05221ac 100755 --- a/packages/ncform-theme-elementui/src/components/control-comps/input.vue +++ b/packages/ncform-theme-elementui/src/components/control-comps/input.vue @@ -38,7 +38,7 @@ v-if="mergeConfig.compound.prependSelect" v-model="prependSelectVal" slot="prepend" - :placeholder="$nclang('selectPls')" + :placeholder="mergeConfig.compound.prependSelect.placeholder || $nclang('selectPls')" >

[CASE] {{ item.title }}

- +