How to restrict upload antd to single file? - reactjs

<Form.Item
name="upload"
label="Upload"
valuePropName="fileList"
getValueFromEvent={normFile}
multiple="false"
>
<Upload accept=".csv" name="logo" multiple="false" action="/upload.do" listType="picture">
<Button icon={<UploadOutlined />}>Click to upload</Button>
</Upload>
</Form.Item>
I wan't to allow user to input only one file.
Also how to read that csv file after uploading and send to the backend (just the params)?
mutiple files are allowed as below

The solution to your first question is very simple. The Ant Design Upload component API (now?) contains maxCount, which limits/controls the number of uploaded files.
Set it to 1 and that will limit the amount of files uploaded to just 1. If a user picks up another file, it will replace the one selected before.
So, you should have something like this in the end:
<Form.Item
name="upload"
label="Upload"
valuePropName="fileList"
getValueFromEvent={normFile}
multiple="false">
<Upload
accept=".csv"
name="logo"
multiple="false"
action="/upload.do"
listType="picture"
maxCount={1} //this is what limits the number of files uploaded
>
<Button icon={<UploadOutlined />}>
Click to upload
</Button>
</Upload>
</Form.Item>

I handle this problem by Css, Check my list array length, if true define a className to the upload button which prevent to click.
const [list, setList] = useState(null);
<Dragger //its one of antd upload components
{...settings}
className={list?.length ? 'blocked' : undefined}
>
.blocked {
pointer-events: none;
opacity: 0.5;
}

Related

How to solve the problem that the file name of antd upload is broken

Currently, in my project, I am using ant-design upload as follows.
<ImageUploaderWrapper
name="images"
rules={[
{
required: true,
},
]}
valuePropName="fileList"
getValueFromEvent={normFile}
initialValue={editPost && [...editPostImages]}
>
<Upload.Dragger
name="image"
multiple
listType="picture"
onChange={onChangeImages}
beforeUpload={onBeforeUpload}
onPreview={onImagePreview}
>
<ImageUploaderText className='bold'>
{editPost ? 'Drag edit files here or' : 'Drag files here OR'}
</ImageUploaderText>
<Button type='primary' size='large' icon={<UploadOutlined />}>Upload</Button>
</Upload.Dragger>
</ImageUploaderWrapper>
I am studying in Korea and often upload file names in Korean.
At this time, if you upload an image file in Korean, it is changed to special characters as follows.
// Upload file name
다운로드.jfif
// Uploaded file name
ë¤ì´ë¡ë_.jfif
I would appreciate it if you could let me know what method I should use to solve this problem.

React Quill - Editing an already published text or saved draft

I am making a react web app in which I want some users to have the ability to post newsletters. I am using react quill as the text editor for this.
The issue I am experiencing is how to edit a saved draft or edit an already published newsletter. I want to pass the appropriate newsletter into the editor when i click on the 'edit-button'. But I could not figure out how on my own, neither could I find anything on the subject.
I am using sequelize for my backend and currently the editor is a popup.
<Popup
trigger={<button
class="btn">
Redigera
</button>}>
<React.StrictMode>
<Editor />
</React.StrictMode>
</Popup>
The editor looks like this. I have a text field where the user puts the title of the newsletter and a date picker if they'd like to set a specific date for when it is to be published.
return (
<div class="overlay">
<button id="closeButton">Stäng och spara</button>
<div className="text-editor">
<EditorToolbar />
<TextField
required
id="required"
fullWidth
label="Titel"
onChange={(e) => setTitle(e.target.value)}
/>
<ReactQuill
theme="snow"
value={content}
onChange={setContent}
placeholder={"Skriv ditt nyhetsbrev här..."}
modules={modules}
formats={formats}
/>
<TextField
id="date"
label="Välj dag för publicering"
type="date"
defaultValue={getCurrentDate()}
onChange={(e) => setPublishedAt(e.target.value)}
sx={{ width: 220 }}
InputLabelProps={{
shrink: true,
}}
/>
<button class="rte-button" onClick={publishNow}>Publicera</button>
<div class="buttons">
<button class="rte-button" onClick={onDelete}>Ta bort</button>
<button class="rte-button" onClick={saveNewsletterAsDraft}>Spara utkast</button>
</div>
</div>
</div>
);
};
export default Editor;
I am doing a findAll to retrieve all the existing newsletters from the backend so what I've been thinking of doing is to pass the content and title of the newsletter i want to edit into the editor as a prop. But I would rather not do that as I am not working with classes.

How to change text of "file" <Input> antd

I believe the title is self-explanatory. I have checked the docs and some other threads, but I simply cannot manage to change both texts of the label: nor "Choose file", neither "No file chosen". Below is what I have tried so far. How could I change those texts?
{/* <label htmlFor="test" id="files">Test with classic label</label> */}
<Input
// addonAfter="test1"
// addonBefore="test2"
type="file"
onChange={handleFileSelected}
text="test"
/>
The text of the input's file element is controlled by the browser so you can not directly change that. What you can do is instead creating a customizable button that uses a ref to control the click on the input:
const ref = useRef<HTMLInputElement>(null);
<button onClick={() => ref.current?.click()}>Click Here</button>
<input
type='file'
ref={ref}
onChange={handleFileSelected}
style={{ display: "none" }} />
Ant Design also has Upload component for file uploading which could be styled easily

How do I use the SpeedDial to upload a file?

(this seem to have been asked previously but I couldn't find any hint on if it was actually answered)
MUI has a good demo for creating upload buttons which boils down to:
<input accept="image/*" className={classes.input} id="icon-button-file" type="file" />
<label htmlFor="icon-button-file">
<IconButton color="primary" aria-label="upload picture" component="span">
<PhotoCamera />
</IconButton>
</label>
What I wonder is how to implement the same using the Speed Dial. Inherently the SpeedDialAction seems to materialize as a <button/>, but it's not possible to e.g. wrap the SpeedDialAction in a <label htmlFor /> as its parent will try to set some props on it and will fail.
So how do I initiate the file selection from within the Speed Dial or a FAB in general?
You can create a wrapper component that forwards props to SpeedDialAction.
function UploadSpeedDialAction(props) {
return (
<React.Fragment>
<input
accept="image/*"
style={{ display: "none" }}
id="icon-button-file"
type="file"
/>
<label htmlFor="icon-button-file">
<SpeedDialAction
icon={<CloudUploadIcon />}
tooltipTitle="upload"
component="span"
{...props}
></SpeedDialAction>
</label>
</React.Fragment>
);
}
https://codesandbox.io/s/material-demo-forked-h6s4l
(Note to future readers: For v5, time allowing, we hope to rationalise where props rather than context are used to control children, in order to solve exactly this kind of issue. So check whether this solution is still needed.)
It is - in my knowledge - not possible to add the htmlFor in any way. So what I would do is to add a hidden input type file and then add a ref to it. Then in the onclick of the SpeedDialAction button I would call a handler function that clicks on the input ref. Like this:
const inputRef = useRef();
const handleFileUploadClick = () => {
inputRef.current.click();
};
Then your SpeedDialAction:
<SpeedDialAction
onClick={handleFileUploadClick}
... the rest of your props
/>
And then finnaly your actual input:
<input
style={{ display: "none" }}
ref={inputRef}
accept="image/*"
id="contained-button-file"
multiple
type="file"
/>
Working demo: https://codesandbox.io/s/material-demo-forked-f9i6q?file=/demo.tsx:1691-1868

reactJS material UI Icon button to upload file

I want to know how can I open the directory to upload a file using an IconButton?
<IconButton
iconClassName="fa fa-plus-square"
onClick={(e) => e.stopPropagation()}
type='file'
/>
using the code below shows the icon button and another button for the upload file
<IconButton iconClassName="fa fa-plus-square" onClick={(e) => e.stopPropagation()}>
<input type="file type='file'>
</IconButton>
I think the standard way from material ui examples:
<input accept="image/*" className={classes.input} id="icon-button-file" type="file" />
<label htmlFor="icon-button-file">
<IconButton color="primary" className={classes.button} component="span">
<PhotoCamera />
</IconButton>
</label>
A few things:
You don't need type='file' on the IconButton, just on the input
IconButton does not expect its children to be anything other than an SVGIcon, so I recommend that you use a regular button
I wouldn't call stopPropagation in this case
You have a typo in your type prop for the input. You have type="file type='file'. It should just be type="file"
So, putting that all together:
<FlatButton label="Choose file" labelPosition="before">
<input type="file" style={styles.exampleImageInput} />
</FlatButton>
If you still want it to be an icon rather than a button, I suspect you can do something with <input> or add it as the children to FlatButton with no label.
You can achieve the same with IconButton using the following code:
<IconButton onClick={() => this.fileUpload.click()}>
<FontIcon className="material-icons" >
add_a_photo
</FontIcon>
</IconButton>
<input type="file" ref={(fileUpload) => {
this.fileUpload = fileUpload;
}}
style={{ visibility: 'hidden'}} onChange={this.groupImgUpload} />

Resources