How to submit form on Enter using DIV - javascript

I'm trying to figure out how to make my form submit when enter is pressed inside the div that is acting as input. Any help?
Here is my code.
const socket = new WebSocket("ws://localhost:5000");
const Chat = () => {
let divText = "";
const SendMessage = (event) => {
event.preventDefault();
console.log(divText);
divText = "";
}
const HandleChange = (event) => {
divText = event.target.textContent;
}
return (
<div className='chat-div'>
<div className='chat-box'>
<span className='razmak'></span>
</div>
<form className='input-form' onSubmit={SendMessage} spellCheck='false'>
<div className='chat-input' contentEditable='true' onInput={HandleChange}></div>
<button className='send-button' type='submit'><AiOutlineSend/></button>
</form>
</div>
)
}
export default Chat;

What I'd do is update your div to use an onKeyDown like this:
const socket = new WebSocket("ws://localhost:5000");
const Chat = () => {
let divText = "";
const sendMessage = (event) => {
alert("submit");
event.preventDefault();
console.log(divText);
divText = "";
};
const handleChange = (e) => {
divText = e.target.textContent;
if (e.key === "Enter") {
sendMessage(e);
}
};
return (
<div className="chat-div">
<div className="chat-box">
<span className="razmak"></span>
</div>
<form className="input-form" onSubmit={sendMessage} spellCheck="false">
<div
className="chat-input"
contentEditable="true"
onKeyDown={(e) => handleChange(e)}
></div>
<button className="send-button" type="submit">
jhgj
</button>
</form>
</div>
);
};
export default Chat;
There's a couple of other things, some which I've not included above:
Lowercase the method names if they don't return JSX
The divText should ideally use the useState React hook
Consider using a standard input rather than a div, as this is semantically more correct, and accessible for people using screen readers.

Related

How to preserve spacing when storing a string into an array? JavaScript React.js

I have a form with a <textarea>. On submit that string gets stored into an array. Sometimes the strings have blank lines or additional spacing and I want to preserve this spacing. Right now, the only spacing preserved is the spacing between words. The handleSubmit component consist of a useRef hook that is pushed into the array. I'm looking for another approach for storing the string that would preserve spacing. I appreciate all ideas! Thank you for your time!
const textAreaRef = useRef();
const [entryArray, setEntry] = useState([]);
const handleSubmit = (event) => {
event.preventDefault();
const updatedList = [...entryArray];
updatedList.push(textAreaRef.current.value);
textAreaRef.current.value = ""; // Clears value
setEntry(updatedList);
}
return (
<div>
<form class="entryForm" onSubmit={handleSubmit} >
<label for="newEntryId">
<span>New Entry:</span>
<textarea type="text" id="newEntryId" name="newEntryName" rows="30" cols="75"
defaultValue="What's on your mind?" ref = {textAreaRef}
/>
</label>
<button type="submit">Submit</button>
</form>
</div>
)
Can't replicate the issue, works fine.
Vanilla js example, but works the same in React
const area = document.querySelector('textarea')
const button = document.querySelector('button')
const saved = []
button.addEventListener('click', () => {
saved.push(area.value)
area.value = ''
console.log(saved)
})
<textarea></textarea>
<button>save</button>

How to validate phone number onClick in React?

I want to validate phone number onClick of a button. This is what I have done, I am new to ReactJS. Please help me in this. When I click submit that time it will show an error message.
const [phoneNo, setPhoneNo] = useState(false)
const [errorMessage, setErrorMessage] = useState("")
const validateFunc = () => {
setPhoneNo(true)
}
const onChangeValidate= (e) => {
var phone = e.target.value;
if( !(phone.match('[0-9]{10}')) ){
setPhoneNo(false);
setErrorMessage("Please enter 10 digit")
}else{
}
setPhoneNo(true)
}
----
<input onChange ={() => onChangeValidate(e)} />
<button onClick = {validateFunc()}>Submit</button>
<p>{errorMessage}</p>
You seem to understand the basic construct of a function component using state but there are a couple of issues.
All event handlers will receive that event as an argument. So you can write <input onChange ={onChangeValidate} /> and <button onClick={validateFunc}>Submit</button>.
It maybe better to use test rather than match in this instance: /[0-9]{10}/.test(phone).
But I also think that you should allow the form to do the validation for you, rather than JS. This way you don't need the error state as the validation is all handled automatically.
Wrap your input and button in a <form> element with its own onSubmit handler, make the input required, and add a type="submit" to the button. You can use CSS to change the style of the input if it's not valid.
const { useState } = React;
function Example() {
const [phoneNo, setPhoneNo] = useState('');
// Update the phone number state when the
// input changes
function handleChange(e) {
setPhoneNo(e.target.value);
}
// In this example prevent the form from
// submitting so we can log the state, but you'll probably
// want to do an AJAX call here to submit the form
function handleSubmit(e) {
e.preventDefault();
console.log(phoneNo);
}
// Add your regex pattern to the input
// and make it required. If you submit an invalid
// number you'll get a neat little tooltip warning
// you of the issue, and the form won't submit until
// it has been fixed
return (
<form onSubmit={handleSubmit}>
<input
pattern="[0-9]{10}"
placeholder="Add a phone number"
onChange={handleChange}
required
/>
<button type="submit">Submit</button>
</form>
);
}
ReactDOM.render(
<Example />,
document.getElementById('react')
);
input:invalid { border: 1px solid red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>
const onChangeValidate= (e) => {
var phone = e.target.value;
if( !(phone.match('[0-9]{10}')) ){
setPhoneNo(false);
setErrorMessage("Please enter 10 digit")
}else{
setPhoneNo(true)
}
}
<p>{setPhoneNo===false?errorMessage:''}</p>
Set like these if there will be setphone no false then msg will be shown
Try this!
const [phoneNo, setPhoneNo] = useState(false)
const [errorMessage, setErrorMessage] = useState("")
const validateFunc = () => {
if(phoneNo) {
// perform submittion
}
}
const onChangeValidate= (e) => {
var phone = e.target.value;
if( !(phone.match('[0-9]{10}')) ){
setPhoneNo(false);
setErrorMessage("Please enter 10 digit");
}else{
setPhoneNo(true);
setErrorMessage("");
}
}
----
<input onChange ={(e) => onChangeValidate(e)} />
<button type="button" onClick = {validateFunc()}>Submit</button>
<p>{errorMessage}</p>

Element renders each time button is clicked

For the sake of practice I am trying to render an element on submitting the form but each time I click the button element renders on the page but it should render only once in the case of an invalid value.
My question is how to execute function renderError() only once, when Submit button is clicked?
The code I'm trying to accomplish this with is:
const form = document.querySelector('.form')
const renderError = () => {
const newElement = document.createElement('div')
newElement.className = 'error'
newElement.innerHTML = `
<img class="error__icon" src="images/icon-error.svg" alt="error icon" />
<p class="error__message">Please provide a valid email</p>
`
const rootElement = document.getElementById('error__container')
rootElement.append(newElement)
}
const validateForm = () => {
const isValid = /^[^\s#]+#[^\s#]+\.[^\s#]+$/
if (isValid.test(email.value)) {
// return something
} else {
renderError()
}
}
form.addEventListener('submit', (e) => {
e.preventDefault()
validateForm()
})
<div class="form__container">
<form class="form" novalidate>
<input type="email" name="email" id="email" aria-label="Email" placeholder="Email Address" />
<div id="error__container"></div>
<button class="submit">
<img src="images/icon-arrow.svg" alt="submit icon">
</button>
</form>
</div>
Don't create a new error element each time. Try to find the one created before (by id, for example). Create it only if you need it. This is often called "lazy" initialization.
// lazily return the error element (create it if we can't find it)
const errorElement = () => {
let element = document.getElementById('errorElement')
if (!element) {
element = document.createElement('div')
element.className = 'error'
element.id = 'errorElement';
const rootElement = document.getElementById('error__container')
rootElement.append(element)
}
return element
}
let count = 0
const validateForm = () => {
const isValid = /^[^\s#]+#[^\s#]+\.[^\s#]+$/
if (isValid.test(email.value)) {
// return something
} else {
const element = errorElement();
element.innerHTML = `something went wrong ${++count} times`
}
}
const form = document.getElementById('myform')
form.addEventListener('submit', (e) => {
e.preventDefault()
validateForm()
})
<div class="form__container">
<form id="myform" class="form" novalidate>
<input type="email" name="email" id="email" aria-label="Email" placeholder="Email Address" />
<div id="error__container"></div>
<button class="submit">Button
</button>
</form>
</div>
One solution: you can clear the contents of the rootElement before re-rendering:
const renderError = () => {
const newElement = document.createElement('div')
newElement.className = 'error'
newElement.innerHTML = `
<img class="error__icon" src="images/icon-error.svg" alt="error icon" />
<p class="error__message">Please provide a valid email</p>
`
const rootElement = document.getElementById('error__container')
rootElement.innerHTML = ""; // <-- Empty before appending
rootElement.append(newElement)
}
Another solution would be to add the newElement in the HTML, hide it using visibility: hidden and then toggle a class on/off that will turn the visibility value to visible and hidden. This way, when the render error runs, it will just add a special class that will display the error element and upon clicking again the element will just get the class enabled again without re-appearing.

how to use prevent default and toggle inside a function?

I'm trying to build a library where the user can write the info and the book and add it to the library. I created a modal form where the user can write the info and submit it.
This is the modal html
<form class="modal__container">
<div class="modal">
<div class="modal__content">
<label for="">Title:</label>
<input type="text" id="title">
</div>
<div class="modal__content">
<label for="">Author:</label>
<input type="text" id="author">
</div>
<div class="modal__content">
<label for="">Pages:</label>
<input type="number" id="pages">
</div>
<label for="">Have you read it?</label>
<div>
<label for="yes">Yes</label>
<input type="radio" name ="read" value="yes">
<label for="no">No</label>
<input type="radio" name ="read" value="no">
</div>
<button class="add__book">Add</button>
<button class="cancel">Cancel</button>
</div>
</form>
This is the function that closes the modal when clicking on the cancel button
function toggle() {
addBtn.addEventListener("click", () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", () => {
modal.style.display = "none";
})
})
}
toggle();
Here I have the constructor and the array to store the books
let myLibrary = [];
function Book(title, author, pages) {
this.title = title,
this.author = author,
this.pages = pages
}
Now I want to create a function that submits the new book
submitBook.addEventListener("click", addBookToLibrary);
function addBookToLibrary() {
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let book = new Book(bookTitle, bookAuthor, bookPages);
myLibrary.push(book);
console.log(bookTitle)
console.log(bookAuthor)
console.log(bookPages)
toggle();
}
I see the info for half a second and then it disappears. I know I should use prevent default somewhere. I tried this
function addBookToLibrary(e) {
e.preventDefault();
let bookTitle = modalTitle.value;
let bookAuthor = modalAuthor.value;
let bookPages = modalPages.value;
let book = new Book(bookTitle, bookAuthor, bookPages);
myLibrary.push(book);
console.log(bookTitle)
console.log(bookAuthor)
console.log(bookPages)
toggle();
}
It displays the info correctly but it doesn't close the modal. How can I fix it?
You currently have an anonymous function that does what you want: close the modal. It's inside another anonymous function which opens the modal:
addBtn.addEventListener("click", () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", () => {
modal.style.display = "none";
});
});
You can "refactor" out two named functions from that code, like so:
const hideModal = () => {
modal.style.display = "none";
};
const showModal = () => {
modal.style.display = "block";
const cancel = document.querySelector(".cancel");
cancel.addEventListener("click", hideModal);
};
addBtn.addEventListener("click", showModal);
Then, inside your other event handlers, you can call either function:
function addBookToLibrary() {
// ...
hideModal();
}

How to check in js that user has checked the checkbox in Google recaptcha?

I have added the following before end of head
<script src='https://www.google.com/recaptcha/api.js'></script>
I have added this before end of form
<div class="g-recaptcha" data-sitekey="== xxxxxx =="></div>
I can see the recaptcha similar to https://developers.google.com/recaptcha/
HOwever, when user presses data without checking the checkbox, the data is submitted. Is there any other code I need to add to check if user has pressed the checkbox? Hopefully in js?
Google has a call back option for when the checkbox is checked.
Add this to your form element:
data-callback="XXX"
Example:
<div class="g-recaptcha" data-callback="recaptchaCallback" data-sitekey="== xxxxxx =="></div>
And a disable attribute to your submit button.
Example:
<button id="submitBtn" disabled>Submit</button>
Then a create a callback function and write whatever code you need.
Example:
function recaptchaCallback() {
$('#submitBtn').removeAttr('disabled');
};
You can also call the grecaptcha object to check. grecaptcha.getResponse(); is empty when unchecked and has the verification code when checked.
grecaptcha.getResponse().length === 0 when unchecked
function isCaptchaChecked() {
return grecaptcha && grecaptcha.getResponse().length !== 0;
}
if (isCaptchaChecked()) {
// ...
}
To check if google recaptcha is checked or not you can do it by the following code :
<script>
if(grecaptcha && grecaptcha.getResponse().length > 0)
{
//the recaptcha is checked
// Do what you want here
alert('Well, recaptcha is checked !');
}
else
{
//The recaptcha is not cheched
//You can display an error message here
alert('Oops, you have to check the recaptcha !');
}
</script>
To check if google recaptcha v2 is checked or not you can do it by the following code :
var checkCaptch = false;
var verifyCallback = function(response) {
if (response == "") {
checkCaptch = false;
}
else {
checkCaptch = true;
}
};
$(document).ready(function() {
$("#btnSubmit").click(function() {
if (checkCaptch && grecaptcha.getResponse()!="") {
//Write your success code here
}
});
})
Let the browser do the job for you! (based on slinky2000 answer)
note: this is only to prevent sending an 'accidentally' unchecked recaptcha. You still have to verify the recaptcha on server side because a bot does not care ...
Add a an invisible input tag with required=true attribute just below the div.g-recaptcha.
<input id='recaptcha_check_empty' required tabindex='-1',
style='width:50px; height:0; opacity:0; pointer-events:none;
position:absolute;
bottom:0;'>
Enclose both width a div with position=relative; to point the bottom:0; above to the bottom of recaptcha.
Now the Browser asks nicely to fill out this field - pointing to the recapcha.
Now we need the callback:
<div class="g-recaptcha" data-callback="recaptchaCallback" ...
and
function recaptchaCallback() {
$('#recaptcha_check_empty').val(1);
}
<div class="contact-inner contact-message">
<label for="message-text" class="col-form-label">CAPTCHA</label>
<div class="g-recaptcha" data-sitekey="<?php echo 6LfSJmocAAAAAFFMpMKB1CtYNJYDyDswO7GpxRXS ;?>">
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src='https://www.google.com/recaptcha/api.js'></script>
<!DOCTYPE html>
<html>
<head>
<title>CAPTCHA</title>
</head>
<body>
<div class="contact-inner contact-message">
<label for="message-text" class="col-form-label">CAPTCHA</label>
<div class="g-recaptcha" data-sitekey="<?php echo GOOGLE_KEY ;?>"></div>
</div>
</body>
</html>
if for some reason you are conditioning a form by hand like me, and required is not working.
First import ReCAPTCHA
import ReCAPTCHA from 'react-google-recaptcha'
Apply it in your component
<ReCAPTCHA style={{margin: '5px', transform: 'scale(0.8)'}} ref={recaptchaRef} sitekey={recaptchaKey} onChange={updateRecaptcha}/>
you can use a useRef or just use the ReCAPTCHA you've imported, I used useRef.
const recaptchaRef = useRef<any>()
And now, how do I check if recaptchaRef is checked?
if (recaptchaRef.current.props.grecaptcha.getResponse().length !== 0) {
//your condition
}
basically, you are saying 'if recaptcha is true, then do this'
this is complete form code that helps you (I'm using typeScipt)
const Formid = // yout formid
const FormSpark = `https://submit-form.com/${Formid}`
type FormState = {
name: string,
mail: string,
message: string
}
const initialState = {
name: '',
mail: '',
message: '',
}
const [wrongmail, setWrongmail] = useState(false)
const [wrongname, setWronname] = useState(false)
const [wrongtext, setWrongtext] = useState(false)
const [alert, setAlert] = useState(false)
const recaptchaRef = useRef<any>()
const recaptchaKey = //your recaptcha public key const [recaptchaToken, setRecaptchaToken] = useState<string>()
const [formstate, setFormState] = useState<FormState>(initialState)
const submit = async(event: FormEvent) =>{
event.preventDefault()
await postSubmission()
}
const updateRecaptcha = (token: string | null)=>{
setRecaptchaToken(token as string)
}
const {name, mail, message} = formstate
const postSubmission = async() => {
const payload = {
...formstate,
"g-recaptcha-response": recaptchaToken
}
try {
if (name && mail && message) {
if (mail.includes('#') && mail.includes('.') && mail.length > 5) {
if (name.includes(' ') && name.length> 5) {
if (message.length > 20) {
if (recaptchaRef.current) {
if (recaptchaRef.current.props.grecaptcha.getResponse().length !== 0) {
console.log('hola')
setAlert(true)
const result = await axios.post(FormSpark, payload)
setFormState(initialState)
recaptchaRef.current.reset()
if (result) {
setTimeout(() => {
setAlert(false)
},2000)
}
}
}
}
}
}
if (!name && !(name.length> 5) && !(name.includes(' '))) {
setWronname(true)
setTimeout(() => {
setWronname(false)
},3000)
}
if (!mail && !mail.includes('#') && !mail.includes('.') && !(mail.length > 5)) {
setWrongmail(true)
setTimeout(()=>{
setWrongmail(false)
},3000)
}
if (!message && !(message.length > 20)) {
setWrongtext(true)
setTimeout(() => {
setWrongtext(false)
},3000)
}
}
} catch(error){
console.log(error);
}
}
const updateForm = (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
const {id, value} = event.target
const formKey = id as keyof FormState
const updatedFormState = {...formstate}
updatedFormState[formKey] = value
setFormState(updatedFormState)
}

Categories

Resources