# Form Component



The main advantage of the [form tag in HTML](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form), is that it supports an action called "submit" that collects the information from the input elements on the form and sends them to the server to be processed by a script that can be specified.

!!! note
    It is only necessary to use the Form component with JustPy when you need to handle [file uploads](../uploading_files) by using an Input with type `file` . In all other cases Input elements can be put on a page without the need to organize them inside a form. 

## The submit Event

In JustPy, forms support the "submit" event that allows similar functionality. The input elements of the form are put in a list and added to the second argument of the event handler under the `form_data` key. In the program below the submit event occurs when an Input element of type `submit` (a button for all practical purposes) is clicked.

```python
import justpy as jp
button_classes = 'bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded m-2'
input_classes = 'border m-2 p-2'

session_data = {}

def form_test():
    wp = jp.WebPage()
    wp.display_url = '/fill_form'
    
    form1 = jp.Form(a=wp, classes='border m-1 p-1 w-64')

    user_label = jp.Label(text='User Name', classes='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2', a=form1)
    in1 = jp.Input(placeholder='User Name', a=form1, classes='form-input')
    user_label.for_component = in1

    password_label = jp.Label(classes='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2 mt-2', a=form1)
    jp.Div(text='Password', classes='block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2', a=password_label)
    jp.Input(placeholder='Password', a=password_label, classes='form-input', type='password')

    check_label = jp.Label(classes='text-sm block', a=form1)
    jp.Input(type='checkbox', a=check_label, classes='form-checkbox text-blue-500')
    jp.Span(text='Send me stuff', a=check_label, classes= 'ml-2')
    submit_button = jp.Input(value='Submit Form', type='submit', a=form1, classes=button_classes)

    def submit_form(self, msg):
        print(msg)
        msg.page.redirect = '/form_submitted'
        session_data[msg.session_id] = msg.form_data

    form1.on('submit', submit_form)

    return wp

@jp.SetRoute('/form_submitted')
def form_submitted(request):
    wp = jp.WebPage()
    wp.display_url = '/thanks'
    jp.Div(text='Thank you for submitting the form', a=wp, classes='text-xl m-2 p-2')
    for field in session_data[request.session_id]:
        if field.type in ['text', 'password']:
            jp.Div(text=f'{field.placeholder}:  {field.value}', a=wp, classes='text-lg m-1 p-1')
        elif field.type == 'checkbox' and field.checked:
            jp.Div(text='We will send you stuff', a=wp, classes='text-lg m-1 p-1')
    return wp

jp.justpy(form_test)
```

In the example above, we set the `redirect` attribute of the page in `submit_form`, the event handler for the submit event. This opens the page generated by the request handler `form_submitted` instead of the page with the form. We could have also modified the same page to show the information.

To make the form information available to the new page, we store it in the global `session_data` dictionary using the session id as the key (it is always added to the `request` argument of the the request handlers and can be accessed as `request.session_id`).

## The Label Component

Notice also the use of the Label component which corresponds to the [label](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) HTML tag. The two methods of associating a Label with an Input component are used above. The first is to set the `for_component` attribute of the Label instance to the Input instance. The second is to add the Input instance to the Label instance. 

