javascript antd上传控件需要动作功能,但我不需要它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51514757/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:35:06  来源:igfitidea点击:

action function is required with antd upload control, but I dont need it

javascriptreactjsantd

提问by Luis Valencia

I am using ant design components and I have an upload input: https://ant.design/components/upload/

我正在使用 ant 设计组件并且我有一个上传输入:https: //ant.design/components/upload/

According to the documentation, action is required on the props.

根据文档,需要对道具采取行动。

However I dont need the file to be posted to an url when uploaded, I need the entire FORM to be submited to a rest endpoint (check handlesubmit function)

但是,我不需要在上传时将文件发布到 url,我需要将整个 FORM 提交到其余端点(检查 handlesubmit 函数)

Trying to go through the documentation, I used the handlechange event to add the file to the state, but the STATUS is never done, so that line is never hit.

尝试阅读文档时,我使用 handlechange 事件将文件添加到状态,但 STATUS 从未完成,因此从未命中该行。

What am I missing here?

我在这里错过了什么?

import React, { Component } from 'react';
import { Input, Upload , Icon, message} from 'antd';
import Form from '../../components/uielements/form';
import Checkbox from '../../components/uielements/checkbox';
import Button from '../../components/uielements/button';
import Notification from '../../components/notification';
import { adalApiFetch } from '../../adalConfig';

const FormItem = Form.Item;

class RegisterTenantForm extends Component {
    constructor(props) {
        super(props);
        this.state = {TenantId: '', TenantUrl: '', CertificatePassword: '', confirmDirty: false, loading: false, buttondisabled: true};
        this.handleChangeTenantUrl = this.handleChangeTenantUrl.bind(this);
        this.handleChangeCertificatePassword = this.handleChangeCertificatePassword.bind(this);
        this.handleChangeTenantId= this.handleChangeTenantId.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleupload = this.handleupload.bind(this);
        this.handleTenantIdValidation = this.handleTenantIdValidation.bind(this);
        this.handleTenantAdminUrl = this.handleTenantAdminUrl.bind(this);

    };

    handleChangeTenantUrl(event){
        this.setState({TenantUrl: event.target.value});
    }

    handleChangeCertificatePassword(event){
        this.setState({CertificatePassword: event.target.value});
    }

    handleChangeTenantId(event){
        this.setState({TenantId: event.target.value});
    }

    beforeUpload(file) {
        const isJPG = file.type === 'image/jpeg';
        if (!isJPG) {
          message.error('You can only upload JPG file!');
        }
    }

    handleupload(info){
        //let files = e.target.files;
        if (info.file.status === 'uploading') {
            this.setState({ loading: true });
            return;
        }

        if (info.file.status === 'done') {
            this.setState({ loading: false });
            this.setState({ 'selectedFile': info.file });
        }

    }

    handleTenantIdValidation(rule, value, callback){
        const form = this.props.form;
        const str = form.getFieldValue('tenantid');

        var re = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
        if (str && !str.match(re)) {
            this.setState({buttondisabled: true});
            callback('Tenant id is not correctly formated id');            
        } 
        else {
            this.setState({buttondisabled: false});
            callback();
        }
    }

    handleTenantAdminUrl(rule, value, callback){
        const form = this.props.form;
        const str = form.getFieldValue('tenantadminurl');

        var re = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!$&'\(\)\*\+,;=.]+$/i;
        if (str && !str.match(re)) {
            this.setState({buttondisabled: true});
            callback('Tenant Url is not correctly formated id');
        } 
        else {
            this.setState({buttondisabled: false});
            callback();
        }
    }


    handleSubmit(e){
        e.preventDefault();
        this.props.form.validateFieldsAndScroll((err, values) => {
            if (!err) {
                /*Notification(
                'success',
                'Received values of form',
                JSON.stringify(values)
                );*/

                let data = new FormData();
                //Append files to form data
                data.append("model", JSON.stringify({ "TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "CertificatePassword": this.state.CertificatePassword }));
                //data.append("model", {"TenantId": this.state.TenantId, "TenantUrl": this.state.TenantUrl, "TenantPassword": this.state.TenantPassword });

                let files = this.state.selectedFile;
                for (let i = 0; i < files.length; i++) {
                  data.append("file", files[i], files[i].name);
                }

                const options = {
                  method: 'put',
                  body: data,
                  config: {
                    headers: {
                      'Content-Type': 'multipart/form-data'
                    }
                  }
                };

                adalApiFetch(fetch, "/Tenant", options)
                  .then(response => response.json())
                  .then(responseJson => {
                    if (!this.isCancelled) {
                      this.setState({ data: responseJson });
                    }
                  })
                  .catch(error => {
                    console.error(error);
                });
            }
        });      
    }



    render() {
        const { getFieldDecorator } = this.props.form;

        const formItemLayout = {
        labelCol: {
            xs: { span: 24 },
            sm: { span: 6 },
        },
        wrapperCol: {
            xs: { span: 24 },
            sm: { span: 14 },
        },
        };
        const tailFormItemLayout = {
        wrapperCol: {
            xs: {
            span: 24,
            offset: 0,
            },
            sm: {
            span: 14,
            offset: 6,
            },
        },
        };
        return (
            <Form onSubmit={this.handleSubmit}>
                <FormItem {...formItemLayout} label="Tenant Id" hasFeedback>
                {getFieldDecorator('tenantid', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant id',
                    },
                    {
                        validator: this.handleTenantIdValidation
                    }],
                })(<Input name="tenantid" id="tenantid" onChange={this.handleChangeTenantId}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate Password" hasFeedback>
                {getFieldDecorator('certificatepassword', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your password!',
                    }
                    ],
                })(<Input type="password" name="certificatepassword" id="certificatepassword" onChange={this.handleChangeCertificatePassword}/>)}
                </FormItem>
                <FormItem {...formItemLayout} label="Tenant admin url" hasFeedback>
                {getFieldDecorator('tenantadminurl', {
                    rules: [
                    {
                        required: true,
                        message: 'Please input your tenant admin url!',
                    },
                    {
                        validator: this.handleTenantAdminUrl
                    }],
                })(<Input name="tenantadminurl" id="tenantadminurl"  onChange={this.handleChangeTenantUrl} />)}
                </FormItem>
                <FormItem {...formItemLayout} label="Certificate File">
                    <Upload  onChange={this.handleupload} beforeUpload={this.beforeUpload}>

                        <Button >
                            <Icon type="upload" /> Click to Upload
                        </Button>
                    </Upload>

                </FormItem>
                <FormItem {...tailFormItemLayout}>
                    <Button type="primary" htmlType="submit" disabled={this.state.buttondisabled}>
                        Register tenant
                    </Button>
                </FormItem>
            </Form>
        );
    }
}

const WrappedRegisterTenantForm = Form.create()(RegisterTenantForm);
export default WrappedRegisterTenantForm;

回答by Ramy Ben Aroya

TL;DR

TL; 博士

Override <Upload/>default upload AJAX implementation with a simulated successful upload.

<Upload/>使用模拟成功上传覆盖默认上传 AJAX 实现。

Solution Demo:
Edit antd upload component as file selector

解决方案演示:
编辑 antd 上传组件作为文件选择器

Full Answer

完整答案

It seems that you are trying to use andt's <Upload/>component simply as file selector, due to the fact that you append the file to formDataby yourself. The reason for never hitting the point where status === "done"is because the file is not really uploaded to anywhere.
Thus, you don't need the file to be uploaded automatically like it should OOB.
All you need is that the onChangewill send you the selected file and you can save it somewhere in the state tree.
<Upload/>renders another component (rc-upload) as its child which handles the actual AJAX upload. You can override this behaviour by passing a customRequestprop to <Upload/>(which will be passed to rc-uploadcomponent).

由于您自己将文件附加到,您似乎试图将andt<Upload/>组件简单地用作文件选择器formData。从来没有达到点的原因status === "done"是因为文件没有真正上传到任何地方。
因此,您不需要像 OOB 那样自动上传文件。
您所需要的只是onChange将所选文件发送给您,您可以将其保存在状态树中的某个位置。
<Upload/>呈现另一个组件 ( rc-upload) 作为其处理实际 AJAX 上传的子组件。您可以通过将customRequest道具传递给<Upload/>(将传递给rc-upload组件)来覆盖此行为。

You can see herewhich options are passed to the request function. Here is an implementation of a dummy request function:

您可以在这里看到哪些选项被传递给请求函数。这是一个虚拟请求函数的实现:

const dummyRequest = ({ file, onSuccess }) => {
  setTimeout(() => {
    onSuccess("ok");
  }, 0);
};

Then you can pass it to <Upload customRequest={dummyRequest}/>
onChangewill still be triggered, but this time with the "done"status, since the dummy request function simulates a flow of successful upload.

然后你可以把它传递给<Upload customRequest={dummyRequest}/>
onChange仍然会被触发,但是这次带"done"状态,因为虚拟请求功能模拟了一个成功上传的流程。

回答by Quincy

According to the official documentation Upload manually:

根据官方文档手动上传

Upload files manually after beforeUploadreturns false.

beforeUpload返回后手动上传文件false

beforeUpload(file) {
    const isJPG = file.type === 'image/jpeg';
    if (!isJPG) {
      message.error('You can only upload JPG file!');
    }
    return false;
}

回答by sandiprb

Extending to @Quincy's answer, you can also use shorthand on component something like this,

扩展到@Quincy 的答案,您还可以在类似这样的组件上使用速记,

<Upload beforeUpload={() => false} />