Creating an HTML form with the submit button outside the form is an unconventional but achievable task. This approach can be useful in certain design scenarios such as when you want to customize the layout or functionality of the submit button independently from the form.

Key Takeaway

  • Create a form with all the fields you need. Create a button outside the form.
  • Add an id to the form to identify it.
  • Reference the form in the button as shown below.
<form id="myForm">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" required>
    
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required>
    <!-- Add more form controls as needed -->
</form>

<button form="myForm" type="button" >Submit</button>

Here is a good scenario of when this would be useful.

I was working on a react app and I wanted to have one button to reveal the hidden form as well as submit the forms data to the backend . This means I had to use condition rendering for the button. This way, when I click the button the first time, it shows the form and when I click it the second time, it submits the data to the backend.

Essentially, I still need two buttons which will be rendered depending on the state of the button.

Now that you understand what I was trying to achieve, Here's a step-by-step guide on how to create an HTML form with the submit button outside the form:

Prerequisites

For this tutorial, we'll use a sample code snippet that includes a form designed for becoming an instructor on a platform. The key elements include:

  • A form with inputs for business name, account number, and bank.
  • A submit button that is initially outside the form.
  • An understanding of React

I have used bootstrap for the styling and antd for the icons. so make sure they are imported in your project. In the end, you will have the whole code if you get confused in between. You can then tweak the code to your needs.

Step 1: Creating the HTML structure

If you are using VSCODE as your code editor, you can generate this boilerplate by typing the ! symbol then press the tab key.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Become an Instructor</title>
</head>

<body>
    <!-- Your content will go here -->
</body>

</html>

Step 2: Form Setup

What makes it possible to have the button outside the form is giving your form an identify (preferably an id) that the button will use to know which form to reference.

Within the body tag, create the form element. In our example, the form has a unique identifier my-form.

<form id='my-form' onSubmit={handleSubmit}>
    <!-- Form controls will be added here -->
</form>

Step 3: Form Controls

Inside the form, add the necessary form controls as shown in the code below. These include text inputs for business name, account number, and bank.

<input type="text" placeholder="Enter Business Name" required class="form-control mb-4 p-4" value={bizname} onChange={e => setBizname(e.target.value)} />

<input type="text" placeholder="Enter Account Number" required class="form-control mb-4 p-4" value={accNumber} onChange={e => setAccNumber(e.target.value)} />

<input type="text" placeholder="Enter Bank Name" required class="form-control mb-4 p-4" value={bank} onChange={e => setBank(e.target.value)} />

Step 4: External Submission Button

Now, create the submit button outside the form. This button will trigger the form submission.

<button form='my-form' disabled={!bizname || !accNumber || !bank || loading} type="submit" class="form-control btn btn-lg btn-primary">
    {loading ? < SyncOutlined spin /> : "Submit"}
</button>

Step 5: Create the Unhide button

Create another button below this one, to be used for the form unhiding. Below is the button.

<Button className='mb-3' type='primary' block shape='round' icon={loading ? <LoadingOutlined /> : <SettingOutlined />} size="large" onClick={becomeInstructor} disabled={user && user.role && user.role.includes("instructor") || loading}>
{loading ? "Processing..." : "Payout Setup"}
</Button>

This is how your code should look like right now:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Become an Instructor</title>
</head>

<body>
    <form id='my-form' onSubmit={handleSubmit}>
    	<input type="text" placeholder="Enter Business Name" required class="form-control           mb-4 p-4" value={bizname} onChange={e => setBizname(e.target.value)} />

        <input type="text" placeholder="Enter Account Number" required class="form-control         mb-4 p-4" value={accNumber} onChange={e => setAccNumber(e.target.value)} />

        <input type="text" placeholder="Enter Bank Name" required class="form-control mb-4         p-4" value={bank} onChange={e => setBank(e.target.value)} />
    </form>
    
    <!------ Button 2 ----->
    <button form='my-form' disabled={!bizname || !accNumber || !bank || loading} type="submit" class="form-control btn btn-lg btn-primary">
    {loading ? < SyncOutlined spin /> : "Submit"}
</button>
    
    <!----- Button 2 ----->
    <Button className='mb-3' type='primary' block shape='round' icon={loading ? <LoadingOutlined /> : <SettingOutlined />} size="large" onClick={becomeInstructor} disabled={user && user.role && user.role.includes("instructor") || loading}>
{loading ? "Processing..." : "Payout Setup"}
</Button>
    
    
</body>
</html>

Step 6: Add Logic to the Buttons

We are going to make some changes to the whole document so that we are able to add logic. For this to be possible, JSX is involved so that you cannot write JavaScript in a html document.

  • The first change is changing the file extension to .jsx rather than .html.

  • We also need to add logic to the buttons. Here is the logic for the buttons.

    {hidden ? (
    <button className='mb-3' type='primary' block shape='round' icon={loading ? <LoadingOutlined /> : <SettingOutlined />} size="large" onClick={becomeInstructor} disabled={user && user.role && user.role.includes("instructor") || loading}>
    {loading ? "Processing..." : "Payout Setup"}
    </button>) 
    : 
    (<button form='my-form' disabled={!bizname || !accNumber || !bank || loading} type="submit" className="form-control btn btn-lg btn-primary">
    {loading ? < SyncOutlined spin /> : "Submit"}
    </button>)}
    

    In this code, I am using the ternary operator {hidden ? (first block) : (second block)} a shorthand for an if-else statement.

    If hidden is true, it renders the first block of JSX inside the parentheses; otherwise, it renders the second block.

  • The next step is to handle the click functionality of the buttons. The first button requires that when it is clicked, the function becomeInstructor is called to unhide the form. While the second requires that when it is clicked, it handles form submision. Below is the code for both functions.

    const becomeInstructor = () => {
            setHidden(false);
    };
    
     const handleSubmit = async (e) => {
            e.preventDefault();
            try {
                const response = await axios.post("/api/make-instructor", { user, bizname,             accNumber, bank });
            } catch (err) {
                console.log("An error occurred", err);
            }
    
        }
    

    Ensure that axios is installed in your project.

  • Now let's put the code together. React works with components. So we need to create a component that will hold the handler function as well as return the html code. In this example I will call my component BecomeInstructor

    const BecomeInstructor = () => { The whole code goes here. }
    
  • Here is the whole code so far.

    const BecomeInstructor = () => {
        
        const becomeInstructor = () => {
            setHidden(false);
          };    
    
     const handleSubmit = async (e) => {
            e.preventDefault();
            try {
                const response = await axios.post("/api/make-instructor", { user, bizname,             accNumber, bank });
            } catch (err) {
                console.log("An error occurred", err);
            }
    
        }
    
    return (
    <>
    <body>
        <form id='my-form' onSubmit={handleSubmit}>
        	<input type="text" placeholder="Enter Business Name" required class="form-control           mb-4 p-4" value={bizname} onChange={e => setBizname(e.target.value)} />
    
            <input type="text" placeholder="Enter Account Number" required class="form-control         mb-4 p-4" value={accNumber} onChange={e => setAccNumber(e.target.value)} />
    
            <input type="text" placeholder="Enter Bank Name" required class="form-control mb-4         p-4" value={bank} onChange={e => setBank(e.target.value)} />
        </form>
        
        <!------ Button 2 ----->
        <button form='my-form' disabled={!bizname || !accNumber || !bank || loading} type="submit" class="form-control btn btn-lg btn-primary">
        {loading ? < SyncOutlined spin /> : "Submit"}
    </button>
        
        <!----- Button 2 ----->
        <Button className='mb-3' type='primary' block shape='round' icon={loading ? <LoadingOutlined /> : <SettingOutlined />} size="large" onClick={becomeInstructor} disabled={user && user.role && user.role.includes("instructor") || loading}>
    {loading ? "Processing..." : "Payout Setup"}
    </Button>
    </>
    )
    }
    
    export default BecomeInstructor;
    
  • The only thing remaining now is to import all the dependencies used in the project. Add them at the top of the document. Here are all the dependencies used.

    import React from 'react'
    import axios from "axios";
    import { Button } from "antd";
    import { SettingOutlined, UserSwitchOutlined, LoadingOutlined } from "@ant-design/icons";
    import { toast } from "react-toastify";
    import { useRouter } from 'next/router';
    

This project will now use one button to show the form and submit the data to the backend.

That was a pretty long explainer. If you wanna see more of these, let me know in the comments section.

Conclusion

Creating an HTML form with the submit button outside the form provides flexibility in design. By following the steps outlined in this tutorial and using the provided code snippet, you can implement this unconventional yet practical approach in your web development projects. Customize the code further based on your specific requirements and integrate it seamlessly into your platform.

If you want a detailed explanation of the functionality let me know down in the comments.

If you read so far, thank you for reading and I wish you success in your coding journey.

Thank you : )

Table of Contents
Great! Next, complete checkout for full access to GeekBits.
Welcome back! You've successfully signed in.
You've successfully subscribed to GeekBits.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info has been updated.
Your billing was not updated.