mirror of
https://github.com/frappe/books.git
synced 2024-12-23 19:39:07 +00:00
Form
- Add Submit Buttons - Disable inputs in submitted form - Simplify FormLayout template
This commit is contained in:
parent
8f2c48c3df
commit
ea441c240b
@ -4,6 +4,8 @@
|
|||||||
v-if="shouldRenderForm"
|
v-if="shouldRenderForm"
|
||||||
:doc="doc"
|
:doc="doc"
|
||||||
@save="save"
|
@save="save"
|
||||||
|
@submit="submit"
|
||||||
|
@revert="revert"
|
||||||
/>
|
/>
|
||||||
<div class="p-3">
|
<div class="p-3">
|
||||||
<form-layout
|
<form-layout
|
||||||
@ -89,6 +91,16 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async submit() {
|
||||||
|
this.doc.set('submitted', 1);
|
||||||
|
await this.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
async revert() {
|
||||||
|
this.doc.set('submitted', 0);
|
||||||
|
await this.save();
|
||||||
|
},
|
||||||
|
|
||||||
onValidate(fieldname, isValid) {
|
onValidate(fieldname, isValid) {
|
||||||
if (!isValid && !this.invalidFields.includes(fieldname)) {
|
if (!isValid && !this.invalidFields.includes(fieldname)) {
|
||||||
this.invalidFields.push(fieldname);
|
this.invalidFields.push(fieldname);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="frappe-form-actions d-flex justify-content-between align-items-center p-3 border-bottom">
|
<div class="frappe-form-actions d-flex justify-content-between align-items-center p-3 border-bottom">
|
||||||
<h5 class="m-0">{{ title }}</h5>
|
<h5 class="m-0">{{ title }}</h5>
|
||||||
<f-button primary :disabled="!isDirty" @click="$emit('save')">{{ _('Save') }}</f-button>
|
<f-button primary v-if="isDirty" @click="$emit('save')">{{ _('Save') }}</f-button>
|
||||||
|
<f-button primary v-if="showSubmit" @click="$emit('submit')">{{ _('Submit') }}</f-button>
|
||||||
|
<f-button secondary v-if="showRevert" @click="$emit('revert')">{{ _('Revert') }}</f-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -11,13 +13,32 @@ export default {
|
|||||||
props: ['doc'],
|
props: ['doc'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isDirty: false
|
isDirty: false,
|
||||||
|
showSubmit: false,
|
||||||
|
showRevert: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.doc.on('change', () => {
|
this.doc.on('change', () => {
|
||||||
this.isDirty = this.doc._dirty;
|
this.isDirty = this.doc._dirty;
|
||||||
|
this.updateShowSubmittable();
|
||||||
});
|
});
|
||||||
|
this.updateShowSubmittable();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
updateShowSubmittable() {
|
||||||
|
this.showSubmit =
|
||||||
|
this.meta.isSubmittable
|
||||||
|
&& !this.isDirty
|
||||||
|
&& !this.doc._notInserted
|
||||||
|
&& this.doc.submitted === 0;
|
||||||
|
|
||||||
|
this.showRevert =
|
||||||
|
this.meta.isSubmittable
|
||||||
|
&& !this.isDirty
|
||||||
|
&& !this.doc._notInserted
|
||||||
|
&& this.doc.submitted === 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
meta() {
|
meta() {
|
||||||
|
@ -11,20 +11,11 @@
|
|||||||
:key="fieldname"
|
:key="fieldname"
|
||||||
:docfield="getDocField(fieldname)"
|
:docfield="getDocField(fieldname)"
|
||||||
:value="$data[fieldname]"
|
:value="$data[fieldname]"
|
||||||
|
:doc="doc"
|
||||||
@change="value => updateDoc(fieldname, value)"
|
@change="value => updateDoc(fieldname, value)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!layout">
|
|
||||||
<frappe-control
|
|
||||||
v-for="docfield in fields"
|
|
||||||
v-if="shouldRenderField(docfield.fieldname)"
|
|
||||||
:key="docfield.fieldname"
|
|
||||||
:docfield="docfield"
|
|
||||||
:value="$data[docfield.fieldname]"
|
|
||||||
@change="value => updateDoc(docfield.fieldname, value)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -85,17 +76,21 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
layoutConfig() {
|
layoutConfig() {
|
||||||
if (!this.layout) return false;
|
let layout = this.layout;
|
||||||
|
|
||||||
let config = this.layout;
|
if (!layout) {
|
||||||
|
const fields = this.fields.map(df => df.fieldname);
|
||||||
if (Array.isArray(config)) {
|
layout = [{
|
||||||
config = {
|
columns: [{ fields }]
|
||||||
sections: config
|
}];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
if (Array.isArray(layout)) {
|
||||||
|
layout = {
|
||||||
|
sections: layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return layout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div ref="wrapper" class="datatable-wrapper"></div>
|
<div ref="wrapper" class="datatable-wrapper"></div>
|
||||||
<div class="table-actions mt-1">
|
<div class="table-actions mt-1" v-if="!disabled">
|
||||||
<f-button danger @click="removeCheckedRows" v-if="checkedRows.length">Remove</f-button>
|
<f-button danger @click="removeCheckedRows" v-if="checkedRows.length">Remove</f-button>
|
||||||
<f-button light @click="addRow" v-if="!checkedRows.length">Add Row</f-button>
|
<f-button light @click="addRow" v-if="!checkedRows.length">Add Row</f-button>
|
||||||
</div>
|
</div>
|
||||||
@ -16,7 +16,7 @@ import FrappeControl from './controls/FrappeControl';
|
|||||||
import { convertFieldsToDatatableColumns } from 'frappejs/client/ui/utils';
|
import { convertFieldsToDatatableColumns } from 'frappejs/client/ui/utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['doctype', 'rows'],
|
props: ['doctype', 'rows', 'disabled'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
docs: this.getRowDocs(),
|
docs: this.getRowDocs(),
|
||||||
@ -121,7 +121,12 @@ export default {
|
|||||||
},
|
},
|
||||||
getColumns() {
|
getColumns() {
|
||||||
const fieldsToShow = this.meta.fields.filter(df => !df.hidden);
|
const fieldsToShow = this.meta.fields.filter(df => !df.hidden);
|
||||||
return convertFieldsToDatatableColumns(fieldsToShow);
|
const columns = convertFieldsToDatatableColumns(fieldsToShow);
|
||||||
|
|
||||||
|
if (this.disabled) {
|
||||||
|
columns.forEach(col => col.editable = false);
|
||||||
|
}
|
||||||
|
return columns;
|
||||||
},
|
},
|
||||||
addRow() {
|
addRow() {
|
||||||
const doc = new Observable();
|
const doc = new Observable();
|
||||||
|
@ -12,7 +12,8 @@ export default {
|
|||||||
onlyInput: {
|
onlyInput: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
}
|
},
|
||||||
|
disabled: Boolean
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
id() {
|
id() {
|
||||||
@ -71,7 +72,7 @@ export default {
|
|||||||
placeholder: '',
|
placeholder: '',
|
||||||
value: this.value,
|
value: this.value,
|
||||||
required: this.docfield.required,
|
required: this.docfield.required,
|
||||||
disabled: this.docfield.disabled
|
disabled: this.disabled
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getInputListeners() {
|
getInputListeners() {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
:docfield="docfield"
|
:docfield="docfield"
|
||||||
:value="value"
|
:value="value"
|
||||||
:onlyInput="onlyInput"
|
:onlyInput="onlyInput"
|
||||||
|
:disabled="isDisabled"
|
||||||
@change="$emit('change', $event)"
|
@change="$emit('change', $event)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@ -26,7 +27,7 @@ import Table from './Table';
|
|||||||
import Text from './Text';
|
import Text from './Text';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: ['docfield', 'value', 'onlyInput'],
|
props: ['docfield', 'value', 'onlyInput', 'doc'],
|
||||||
computed: {
|
computed: {
|
||||||
component() {
|
component() {
|
||||||
if (this.docfield.template) {
|
if (this.docfield.template) {
|
||||||
@ -36,7 +37,7 @@ export default {
|
|||||||
extends: Base,
|
extends: Base,
|
||||||
render: null,
|
render: null,
|
||||||
template: this.docfield.template()
|
template: this.docfield.template()
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -54,11 +55,24 @@ export default {
|
|||||||
Password,
|
Password,
|
||||||
Select,
|
Select,
|
||||||
Table,
|
Table,
|
||||||
Text,
|
Text
|
||||||
}[this.docfield.fieldtype];
|
}[this.docfield.fieldtype];
|
||||||
|
},
|
||||||
|
isDisabled() {
|
||||||
|
let disabled = this.docfield.disabled;
|
||||||
|
|
||||||
|
if (this.doc && this.doc.submitted) {
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.docfield.formula && this.docfield.fieldtype !== 'Table') {
|
||||||
|
disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Boolean(disabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.form-group {
|
.form-group {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<model-table
|
<model-table
|
||||||
:doctype="docfield.childtype"
|
:doctype="docfield.childtype"
|
||||||
:rows="value"
|
:rows="value"
|
||||||
|
:disabled="disabled"
|
||||||
@update:rows="emitChange"
|
@update:rows="emitChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
required: this.docfield.required,
|
required: this.docfield.required,
|
||||||
rows: 3
|
rows: 3,
|
||||||
|
disabled: this.disabled
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getDomProps() {
|
getDomProps() {
|
||||||
|
Loading…
Reference in New Issue
Block a user