mirror of
https://github.com/vxcontrol/ncform.git
synced 2026-07-21 06:15:23 -04:00
feat(input and textarea): add updateOn config for iput and textarea
This commit is contained in:
@@ -36,6 +36,7 @@ If you don't like the cold text description, click on the [interactive version](
|
||||
modelField: '', // Used when the value is an object (ie using compound.prependSelect or compound.appendSelect)
|
||||
trim: true, // Whether to automatically trim the front and rear spaces, the default is true
|
||||
clearable: false, // Whether it can be emptied, the default is false
|
||||
updateOn: 'change', // Timing of triggering value changes, the default is to trigger when value changed. Optional value: ['change', 'blur']
|
||||
|
||||
autocomplete: { // Automatic completion
|
||||
itemValueField: 'value', // Item data represents the field of value
|
||||
@@ -114,6 +115,7 @@ If you don't like the cold text description, click on the [interactive version](
|
||||
{
|
||||
rows: 2, // Rows
|
||||
autoSize: true, // Adaptive content height, optional: [boolean | { minRows: 2, maxRows: 6 }]
|
||||
updateOn: 'change', // Timing of triggering value changes, the default is to trigger when value changed. Optional value: ['change', 'blur']
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
modelField: '', // 当值为对象时使用(即使用compound.prependSelect或compound.appendSelect)
|
||||
trim: true, // 是否自动将前后空格trim掉,默认为true
|
||||
clearable: false, // 是否可清空,默认为false
|
||||
updateOn: 'change', // 触发值更新的时机,默认是输入变化即触发。可选值:['change', 'blur']
|
||||
|
||||
autocomplete: { // 自动补全
|
||||
itemValueField: 'value', // 项数据表示value的字段
|
||||
@@ -114,6 +115,7 @@
|
||||
{
|
||||
rows: 2, // 行数
|
||||
autoSize: true, // 自适应内容高度,可选值:[boolean | { minRows: 2, maxRows: 6 }]
|
||||
updateOn: 'change', // 触发值更新的时机,默认是输入变化即触发。可选值:['change', 'blur']
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -846,4 +846,80 @@ context('input', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('updateOn config', () => {
|
||||
|
||||
let formSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
value1: {
|
||||
type: 'string',
|
||||
valueTemplate: 'dx: {{$root.name1}}'
|
||||
},
|
||||
name1: {
|
||||
type: 'string',
|
||||
ui: {
|
||||
widgetConfig: {
|
||||
updateOn: 'blur',
|
||||
autocomplete: {
|
||||
itemValueField: 'name',
|
||||
enumSource: [{ name: 'daniel' }, { name: 'sarah' }],
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
value2: {
|
||||
type: 'string',
|
||||
valueTemplate: 'dx: {{$root.name2}}'
|
||||
},
|
||||
name2: {
|
||||
type: 'string',
|
||||
ui: {
|
||||
widgetConfig: {
|
||||
updateOn: 'blur',
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
cy.window()
|
||||
.its('editor')
|
||||
.invoke('setValue', JSON.stringify(formSchema, null, 2));
|
||||
common.startRun();
|
||||
|
||||
cy.get('body').as('body');
|
||||
|
||||
cy.get('.previewArea').within(() => {
|
||||
|
||||
cy.get('label').contains('value1').parent().find('input').as('value1Input');
|
||||
cy.get('label').contains('value2').parent().find('input').as('value2Input');
|
||||
|
||||
// Declare action elements
|
||||
cy.get('label')
|
||||
.contains('name1')
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get('input').type('da');
|
||||
cy.get('@body')
|
||||
.find('li:contains("daniel")')
|
||||
.click();
|
||||
cy.get('input').should('have.value', 'daniel');
|
||||
cy.get('@value1Input').should('have.value', 'daniel');
|
||||
cy.get('input').type('hi');
|
||||
cy.get('@value1Input').should('have.value', 'daniel');
|
||||
cy.get('input').blur();
|
||||
cy.get('@value1Input').should('have.value', 'danielhi');
|
||||
});
|
||||
|
||||
cy.get('label')
|
||||
.contains('name2')
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get('input').type('daniel');
|
||||
cy.get('@value2Input').should('have.value', '');
|
||||
cy.get('input').blur();
|
||||
cy.get('@value2Input').should('have.value', 'daniel');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+45
@@ -231,4 +231,49 @@ context('textarea', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('updateOn config', () => {
|
||||
|
||||
let formSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
value1: {
|
||||
type: 'string',
|
||||
valueTemplate: 'dx: {{$root.name1}}'
|
||||
},
|
||||
name1: {
|
||||
type: 'string',
|
||||
ui: {
|
||||
widget: 'textarea',
|
||||
widgetConfig: {
|
||||
updateOn: 'blur',
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
cy.window()
|
||||
.its('editor')
|
||||
.invoke('setValue', JSON.stringify(formSchema, null, 2));
|
||||
common.startRun();
|
||||
|
||||
cy.get('body').as('body');
|
||||
|
||||
cy.get('.previewArea').within(() => {
|
||||
|
||||
cy.get('label').contains('value1').parent().find('input').as('value1Input');
|
||||
|
||||
// Declare action elements
|
||||
cy.get('label')
|
||||
.contains('name1')
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get('textarea').type('daniel');
|
||||
cy.get('@value1Input').should('have.value', '');
|
||||
cy.get('textarea').blur();
|
||||
cy.get('@value1Input').should('have.value', 'daniel');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -583,7 +583,26 @@ The description of each field of upload is as follows:
|
||||
- headers: set the request headers for the upload
|
||||
`
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
cn: '[属性] updateOn: 触发值更新的时机,默认是输入变化即触发。可选值:["change", "blur"]',
|
||||
en: '[ATTR] updateOn: timing of triggering value changes, the default is to trigger when value changed. Optional value: ["change", "blur"]'
|
||||
},
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
ui: {
|
||||
widgetConfig: {
|
||||
updateOn: 'blur'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
// Bootstrap the app
|
||||
|
||||
@@ -176,7 +176,27 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
cn: '[属性] updateOn: 触发值更新的时机,默认是输入变化即触发。可选值:["change", "blur"]',
|
||||
en: '[ATTR] updateOn: timing of triggering value changes, the default is to trigger when value changed. Optional value: ["change", "blur"]'
|
||||
},
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
ui: {
|
||||
widget: 'textarea',
|
||||
widgetConfig: {
|
||||
updateOn: 'blur'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
// Bootstrap the app
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
:type="mergeConfig.type === 'file' ? 'text' : mergeConfig.type"
|
||||
:prefix-icon="mergeConfig.prefixIcon"
|
||||
:suffix-icon="mergeConfig.suffixIcon"
|
||||
@blur="onBlur"
|
||||
v-model="inputVal"
|
||||
>
|
||||
<template v-if="mergeConfig.type !== 'file' && mergeConfig.compound">
|
||||
@@ -97,6 +98,8 @@
|
||||
:trigger-on-focus="!!mergeConfig.autocomplete.immediateShow"
|
||||
:value-key="mergeConfig.autocomplete.itemValueField || 'value'"
|
||||
v-model="inputVal"
|
||||
@select="onSelectSuggectionItem"
|
||||
@blur="onBlur"
|
||||
>
|
||||
<template
|
||||
slot-scope="props"
|
||||
@@ -223,7 +226,7 @@ export default {
|
||||
|
||||
created() {
|
||||
this.$watch("inputVal", (newVal, oldVal) => {
|
||||
if (!newVal && !oldVal) return;
|
||||
if ((!newVal && !oldVal) || this.mergeConfig.updateOn === 'blur') return;
|
||||
let val = this._processModelVal();
|
||||
this.$emit("input", val);
|
||||
});
|
||||
@@ -333,6 +336,7 @@ export default {
|
||||
prefixIcon: "",
|
||||
suffixIcon: "",
|
||||
modelField: "",
|
||||
updateOn: 'change', // change or blur
|
||||
|
||||
// autocomplete: { // 自动补全
|
||||
// itemLabelField: 'label', // 项数据表示label的字段
|
||||
@@ -561,6 +565,20 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
onBlur() {
|
||||
if (this.mergeConfig.updateOn === 'blur') {
|
||||
let val = this._processModelVal();
|
||||
this.$emit("input", val);
|
||||
}
|
||||
},
|
||||
|
||||
onSelectSuggectionItem() {
|
||||
if (this.mergeConfig.updateOn === 'blur') {
|
||||
let val = this._processModelVal();
|
||||
this.$emit("input", val);
|
||||
}
|
||||
},
|
||||
|
||||
_getFractionalExpression(value, threshold) {
|
||||
let i = 1,
|
||||
j = 1;
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
v-show="!hidden"
|
||||
:placeholder="placeholder"
|
||||
type="textarea"
|
||||
v-model="modelVal"
|
||||
v-model="inputVal"
|
||||
:rows="mergeConfig.rows"
|
||||
:autosize="mergeConfig.autoSize"
|
||||
@blur="onBlur"
|
||||
></el-input>
|
||||
</template>
|
||||
|
||||
@@ -24,15 +25,21 @@
|
||||
|
||||
mixins: [controlMixin],
|
||||
|
||||
created() {
|
||||
this.$data.inputVal = this.$data.modelVal;
|
||||
},
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
updateOn: 'change', // change or blur
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
inputVal: '',
|
||||
// 组件特有的配置属性
|
||||
defaultConfig: {
|
||||
rows: 2,
|
||||
@@ -42,12 +49,23 @@
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
inputVal(newVal, oldVal) {
|
||||
if ((!newVal && !oldVal) || this.mergeConfig.updateOn === 'blur') return;
|
||||
this.$data.modelVal = newVal;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
// disabled / readonly / hidden / placeholder 你可以直接使用这些变量来控制组件的行为
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
onBlur() {
|
||||
if (this.mergeConfig.updateOn === 'blur') {
|
||||
this.$data.modelVal = this.$data.inputVal;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user