antd form Form Data Echo Operation
- 2021-09-12 00:00:13
- OfStack
index page has one table and one new button. Click the new button or table edit to pop up the form module. If it is editing, the data in the corresponding table will be echoed
//index Page
import React from 'react'
import { Table, Button, message, Input, Select, Modal, } from 'antd';
const Option = Select.Option;
import AddOrEdit from './AddOrEdit '
class List extends React.Component {
constructor(props) {
super(props);
}
state = {
id: "",
selectOpt: {
getPopupContainer: () => {
return this.refs.myForm
}
},
tableOption: {
// Header
columns: [
{ title: ' Name of Employee ', key: 'workerName', dataIndex: 'workerName' },
{ title: ' Employee number ', key: 'workNumber', dataIndex: 'workNumber' },
{
title: " Operation ", key: 'action', className: 'columnsCenter', render: (text, record) => {
return (
<a title=" Edit " type="edit" onClick={this.addOrEditClick.bind(this, record)}> Edit </a>
)
}
}
],
dataSource: [], // Table total data
loading: false,
scroll: { x: 1600 },
// Paging initial data
pagination: {
current: 1, pageSize: 10, total: 0, showTotal: total => ` Altogether ${total} Article `
}
},
// Edit form details
dataForm: {
data: [],
model: {
id: { value: undefined },
workerName: { value: undefined },// Name of Employee
workNumber: { value: undefined }// Employee number
},
param: {}
},
//form Form module
modalOption: {
title: " Add / Modify ",
visible: false,
footer: null,
destroyOnClose: true,
width: 900
},
}
// Edit data echo
addOrEditClick(record) {
const self = this;
let { modalOption, dataForm } = this.state;
dataForm.param = JSON.parse(JSON.stringify(dataForm.model));
// If you edit the pop-up form and the data is echoed, otherwise it is added
if (record.id) {
api.get(APIS.yluAssessTarget + record.id).then(function (response) {
const data = response.data.data;
dataForm.param.id.value = data.id;
// To
dataForm.param.workerName.value = data.workerName;
dataForm.param.workNumber.value = data.workNumber;
modalOption.visible = true;
self.setState({ modalOption, dataForm });
});
} else {
modalOption.visible = true;
self.setState({ modalOption });
}
}
// Paging
onTableChange(pagination, filters, sorte) {
if (pagination.current) {
let { tableOption, searchObj } = this.state;
tableOption.pagination.current = pagination.current;
tableOption.pagination.pageSize = pagination.pageSize;
this.setState({ tableOption });
}
this.loadTable();
};
/**
* Initialization list
*/
loadTable() {
let self = this, { tableOption } = this.state;
tableOption.loading = true;
self.setState({ tableOption });
api.post(APIS.yluAssessTargetSearch + '?current=' + tableOption.pagination.current + '&pageSize=' + tableOption.pagination.pageSize, {
data: {
companyName: " Query parameters "// Branch name
}
}).then(function (response) {
tableOption.dataSource = response.data.data.
tableOption.pagination.total = response.data.data.total;
}).finally(() => {
tableOption.loading = false;
self.setState({ tableOption, notDataLevelGroup, searchObj });
});
}
render() {
const self = this;
let { tableOption, modalOption, dataForm } = this.state;
return (
<div>
<Button size="small" type="primary" onClick={this.addOrEditClick.bind(this, 0)} > Add </Button>
<Table {...tableOption} bordered onChange={this.onTableChange.bind(this)} />
<Modal {...modalOption} >
{modalOption.visible ? <AddOrEdit {...dataForm} /> : null}
</Modal>
</div>
)
}
componentDidMount() {
this.loadTable();
}
}
//form Form page , When you click Edit or Add, it will pop up, and when you edit, a drop-down box will be displayed value The value is the current value of the table 1 The value corresponding to the bar data
// Right select Inside value Value with getFieldDecorator Bind
import React from 'react'
import { Table, Button, Select, Form, message, Row, Col, } from 'antd';
const Option = Select.Option;
class AddOrEdit extends React.Component {
// Submit to save
handleSubmit(e) {
e.preventDefault();
const self = this;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
// Submit to save
api.post(APIS.yluAssessTarget, {
data: {
...values,
}
}).then(res => {
message.success(res.data.message)
}).finally(() => {
self.setState({ addOrEditFooterLoading: false })
})
}
});
}
render() {
const { workerNameList, workNumberList} = this.state;
const { getFieldDecorator } = this.props.form;
const reqMeg = ' Cannot be empty ';
const renderOption = (arr, code, name) => arr ? arr.map((item, index) => {
return (<Option key={index + item[code]} value={typeof (item[code]) === 'number' ? item[code].toString() : item[code]}>{item[name]}</Option>)
}) : null
return (
<Form styleName="form_box" onSubmit={this.handleSubmit.bind(this)} >
<Col {...span24}>
<FormItem label=" Name of Employee " {...formItemLayout} hasFeedback>
{getFieldDecorator('workerName', {
rules: [{ required: true, message: reqMeg }]
})(<Select
placeholder=" Please select "
>
{renderOption(workerNameList, 'workCode', 'name')}
</Select>)}
</FormItem>
</Col>
<Col {...span24}>
<FormItem label=" Employee number " {...formItemLayout} hasFeedback>
{getFieldDecorator('workNumber', {
rules: [{ required: true, message: reqMeg }]
})(<Select
placeholder=" Please select "
>
{renderOption(workNumberList, 'workNumber', 'name')}
</Select>)}
</FormItem>
</Col>
</Form>
)
}
}
export default AddOrEdit;
Supplementary knowledge: a-upload components in Ant Design Vue implement the front and back end processing scheme of file list upload and update echo through axios
Preface
In the rapid development of enterprise applications, we need to complete some functions as soon as possible. If you use Ant Design Vue, you can't wait to find an article that can cure all diseases when developing the related functions of uploading files to the form. It is precisely because of this that this article was born, and you are willing to use this article to solve your worries.
Scheme design
Front-end scheme design
Rewrite the file upload mode of a-upload and use axios to upload
Select a file and upload it immediately. The front end records name and uid after uploading successfully, and constructs an instance of File for echoing the uploaded file list of a-upload components
Turn the file list into an uid list to be processed by the backend before submission
Back-end scheme design
Provides an interface for uploading a single file. After each file is selected, it will be uploaded to the interface and written into the file data table of the database
After the new form data is created, bind the current entity record to the uploaded file list
After updating the form data, all the file lists of the entity records are detected, the file lists of uid that are not in the list are deleted, and then all the uid file records in the list are bound with the current entity records
New and updated 1-dimensional treatment scheme
Because the update form needs to be formatted in the same way as the newly selected file after reading the old data, the processing flow here is 1, the data echoed is 1, and the submitted form is also submitted to the existing uid list in the file table, so the data structure here is 1, and the processing will be more concise and clear.
Let the code speak
In order to make it easy for you to understand, the code is directly on, hoping to make the whole thing clear.
Build a form
<a-form :form="form">
<a-form-item label=" Name " style="margin-bottom: 0;">
<a-input v-decorator="['name', {rules: [{required: true, message: ' Please enter a name! '}]}]" />
</a-form-item>
<a-form-item>
<a-upload
:multiple="true"
:fileList="downloadFiles"
:remove="handleDownloadFileRemove"
:customRequest="downloadFilesCustomRequest"
>
<a-button class="upload-btn"> <a-icon type="upload" > Related downloads </a-button>
</a-upload>
</a-form-item>
</a-form>
Write js code
Request token, header, baseUrl, etc. of the back-end interface. I have already configured it in the 1 setup of axios by default
To simplify axios related operations, we encapsulate axios as follows (you can also use axios completely to commit data directly, etc.):
const dibootApi = {
get (url, params) {
return axios.get(url, {
params
})
},
upload(url, formData) {
return service({
url,
method: 'POST',
data: formData
})
}
}
export default dibootApi
By default, we need to upload 1 file list in demo entity
export default {
name: 'demoForm',
data () {
title: ' New ', // Feature title of the form
form: this.$form.createForm(this), // Form data initialization, nothing to say
model: {}, // If you are updating the form, put the previous data here to initialize the display of the data
downloadFiles: [] // List of files that have been uploaded
},
methods: {
// When the form is initially opened (if the form is updated, the relevant data needs to be read out first)
async open (id) {
if (id === undefined) {
// No id Data is considered as new
this.model = {}
this.afterOpen()
} else {
// Otherwise, it is treated as an update
const res = await dibootApi.get(`/${this.name}/${id}`)
if (res.code === 0) {
this.model = res.data
this.title = ' Edit '
this.afterOpen(id)
} else {
this.$notification.error({
message: ' Failed to get data ',
description: res.msg
})
}
}
},
// Update the action of the form after reading data
afterOpen (id) {
// After obtaining the record information, the related operation of file list is echoed
dibootApi.post(`/demo/getFiles/${id}`).then(res => {
if (res.code === 0){
if (res.data.downloadFile !== undefined){
res.data.downloadFile.forEach(data => {
this.downloadFiles.push(this.fileFormatter(data))
})
}
}
})
},
// Rewrite a-upload How to upload files based on
downloadFilesCustomRequest (data) {
this.saveFile(data)
},
// Upload and save files
saveFile (data){
const formData = new FormData()
formData.append('file', data.file)
dibootApi.upload('/demo/upload', formData).then((res) => {
if (res.code === 0){
let file = this.fileFormatter(res.data)
// After uploading a single file, the file will be sent to the first a-upload Actions in the uploaded files list of the component
this.downloadFiles.push(file)
} else {
this.$message.error(res.msg)
}
})
},
// Format the data returned after uploading successfully, and format a-upload The format that can be displayed in the uploaded list (this format is given in the official document)
fileFormatter(data) {
let file = {
uid: data.uuid, // File only 1 Identity, recommended to be set to negative, prevented and internally generated id Conflict
name: data.name, // Filename
status: 'done', // Status: uploading done error removed
response: '{"status": "success"}', // Server response content
}
return file
},
// Yes, when deleting an uploaded file, it is called here
handleDownloadFileRemove (file) {
const index = this.downloadFiles.indexOf(file)
const newFileList = this.downloadFiles.slice()
newFileList.splice(index, 1)
this.downloadFiles = newFileList
},
// Form verification depends on him, but it is still possible to submit the 1 Some data do some hands and feet
validate () {
return new Promise((resolve, reject) => {
this.form.validateFields((err, fieldsValue) => {
if (!err) {
// Set up the list of uploaded files
const downloadFiles = this.downloadFiles.map(o => {
return o.uid
})
const values = {
...fieldsValue,
'downloadFiles': downloadFiles
}
resolve(values)
} else {
reject(err)
}
})
})
},
// Actions related to form submission
async onSubmit () {
const values = await this.validate()
try {
let result = {}
if (this.model.id === undefined) {
// Add this record
result = await this.add(values)
} else {
// Update the record
values['id'] = this.model.id
result = await this.update(values)
}
// Execute the submitted successfully 1 Series of follow-up operations
this.submitSuccess(result)
} catch (e) {
// Object that failed to perform the commit 1 Series of follow-up operations
this.submitFailed(e)
}
},
// Operation of adding data
async add (values) {
....
},
// The operation of updating data
async update (values) {
...
}
}
}
Write interface code related to SpringBoot
DemoController
/***
* Get a list of file information
* @param id
* @return
* @throws Exception
*/
@PostMapping("/getFiles/{id}")
public JsonResult getFilesMap(@PathVariable("id") Serializable id) throws Exception{
List<File> files = fileService.getEntityList(
Wrappers.<File>lambdaQuery()
.eq(File::getRelObjType, Demo.class.getSimpleName())
.eq(File::getRelObjId, id)
);
return new JsonResult(Status.OK, files);
}
/***
* Upload a file
* @param file
* @param request
* @return
* @throws Exception
*/
@PostMapping("/upload")
public JsonResult upload(@RequestParam("file") MultipartFile file) throws Exception {
File fileEntity = demoService.uploadFile(file);
return new JsonResult(Status.OK, fileEntity, " Upload File Successfully ");
}
/***
* Related processing after successful creation
* @param entity
* @return
*/
@Override
protected String afterCreated(BaseEntity entity) throws Exception {
DemoDTO demoDTO = (DemoDTO) entity;
// Update file association information
demoService.updateFiles(new ArrayList<String>(){{
addAll(demoDTO.getDownloadFiles());
}}, demoDTO.getId(), true);
return null;
}
/***
* Related processing after successful update
* @param entity
* @return
*/
@Override
protected String afterUpdated(BaseEntity entity) throws Exception {
DemoDTO demoDTO = (DemoDTO) entity;
// Update file association information
demoService.updateFiles(new ArrayList<String>(){{
addAll(demoDTO.getDownloadFiles());
}}, demoDTO.getId(), false);
return null;
}
DemoService
@Override
public File uploadFile(MultipartFile file) {
if(V.isEmpty(file)){
throw new BusinessException(Status.FAIL_OPERATION, " Please upload pictures ");
}
String fileName = file.getOriginalFilename();
String ext = fileName.substring(fileName.lastIndexOf(".")+1);
String newFileName = S.newUuid() + "." + ext;
//TODO: Validation of legitimate file types is required
if(FileHelper.isImage(ext)){
throw new BusinessException(Status.FAIL_OPERATION, " Please upload a valid file type ");
};
// Description: Here is our processing flow, and the readers need to save and process the documents according to their own needs (after that, our File After the component is open source, you can also follow the processing here.)
String filePath = FileHelper.saveFile(file, newFileName);
if(V.isEmpty(filePath)){
throw new BusinessException(Status.FAIL_OPERATION, " Picture upload failed ");
}
File fileEntity = new File();
fileEntity.setRelObjType(Demo.class.getSimpleName());
fileEntity.setFileType(ext);
fileEntity.setName(fileName);
fileEntity.setPath(filePath);
String link = "/file/download/" + D.getYearMonth() + "_" + newFileName;
fileEntity.setLink(link);
boolean success = fileService.createEntity(fileEntity);
if (!success){
throw new BusinessException(Status.FAIL_OPERATION, " Failed to upload file ");
}
return fileEntity;
}
@Override
public void updateFiles(List<String> uuids, Long currentId, boolean isCreate) {
// If it is not created, you need to delete the file Record
if (!isCreate){
fileService.deleteEntities(Wrappers.<File>lambdaQuery().notIn(File::getUuid, uuids));
}
// Make relevant updates
boolean success = fileService.updateEntity(
Wrappers.<File>lambdaUpdate()
.in(File::getUuid, uuids)
.set(File::getRelObjType, Demo.class.getSimpleName())
.set(File::getRelObjId, currentId));
if (!success){
throw new BusinessException(Status.FAIL_OPERATION, " Failed to update file information ");
}
}
Prompt
This article all code is the program example, which has some deletions, does not ensure that can run directly, if you have a good idea, welcome a discussion.