More scalable applications only using forms and webcomponents
Tags: webcomponents, react, preact, html
Published: 2022-04-02 19:16:21

---
title: More scalable applications only using forms and webcomponents
published: true
description: A powerful form submission manager created with Atomicojs webcomponents
tags: webcomponents, react, preact, html
series: AtomicoJs projects
//cover_image: https://direct_url_to_image.jpg
---

I present to you @atomico/magic-form a set of webcomponents created with [AtomicoJS](https://atomicojs.github.io/) that centralizes form submission to build scalable applications using traditional forms.

**Traditional forms?** I mean the use of the `<form>` tag, example:


```jsx
<form actio="myAction">
  <input type="name" />
  <button>submit</button>
</form>
```

Now let's add some of the magic of MagicForm.

```jsx
<MagicFormProvider
  actions={{
    async myAction(form: HTMLFormElement) {
      return myApi(new FormData(form));
    },
  }}
>
  <MagicForm>
    <form actio="myAction">
      <input type="name" />
      <button>submit</button>
    </form>
  </MagicForm>
</MagicFormProvider>
```

In the above code we have added 2 components:

`MagicFormProvider`: centralizes the actions of nested MagicForms.

`MagicForm`: identifies the form to be observed by MagicFormProvider, this component also allows knowing the status of the sending and the return of the myAction function through the onChangeState event

The benefits of using MagicForm are:

**1. Reusable Actions**

Thanks to MagicFormProvider we can easily reuse the actions between forms, example:

```jsx
<MagicFormProvider
  actions={{
    async myAction(form: HTMLFormElement) {
      return myApi(new FormData(form));
    },
  }}
>
  <MagicForm>
    <form actio="myAction">
      <input type="name" />
      <button>submit</button>
    </form>
  </MagicForm>
  <MagicForm>
    <form actio="myAction">
      <input type="name" />
      <button>submit</button>
    </form>
  </MagicForm>
</MagicFormProvider>;
```

**2. Observe the status of the form**

The form submission process can be observed through the onChangeState event, this will allow you to know the submission status and the action response:

```jsx
<MagicForm
  onChangeState={({ currentTarget }) => {
    console.log(currentTarget.state);
  }}
>
  <form actio="myAction">
    <input type="name" />
    <button>submit</button>
  </form>
</MagicForm>
```

**3. Microfrontend**

If MagicFormProvider does not find the dispatched action among its actions, it will continue to bubble until the next MagicFormProvider, this allows you to have multiple islands with isolated and reusable actions, example:

```jsx
<MagicFormProvider actions={{
    async login(){...}
}}>
    <MagicFormProvider actions={actionsClient}>
        <PageClient/>
    </MagicFormProvider>
    <MagicFormProvider actions={actionsAdmin}>
        <PageAdmin/>
    </MagicFormProvider>
</MagicFormProvider>
```

## Beautiful isn't it? but how to use it

1. Webcomponent
2. AtomicoJS: Atomico is a powerful library that allows you to create web components like MagicForm
3. React and Preact

### Webcomponent

```html
<magic-form-provider>
  <magic-form>
    <form action="user">
      <input type="text" name="name" />
      <input type="text" name="email" />
      <button>Create user</button>
    </form>
  </magic-form>
</magic-form-provider>
<script>
  await customElements.whenDefined("magic-form-provider");

   document.querySelector("magic-form-provider").actions = {
     async add(form) {
       return fetch("./my-api", {
         method: "post",
         body: new FormData(form),
       }).then((res) => res.json());
     },
   };
</script>
```

### Atomico Js

```jsx
import { MagicForm, MagicFormProvider } from "@atomico/magic-form";

function component() {
  return (
    <host>
      <MagicFormProvider
        actions={{
          async add(form) {
            return fetch("./my-api", {
              method: "post",
              body: new FormData(form),
            }).then((res) => res.json());
          },
        }}
      >
        <MagicForm>
          <form action="user">
            <input type="text" name="name" />
            <input type="text" name="email" />
            <button>Create user</button>
          </form>
        </MagicForm>
      </MagicFormProvider>
    </host>
  );
}
```

### React and Preact

To use this webcomponents in React or Preact you must install `@atomico/react`, remember that for its use in Preact you must change the module from `"@atomico/magic-form/react"` to `"@atomico/magic-form/preact"`

```jsx
import { MagicForm, MagicFormProvider } from "@atomico/magic-form/react";

export function App() {
  return (
    <>
      <MagicFormProvider
        actions={{
          async add(form) {
            return fetch("./my-api", {
              method: "post",
              body: new FormData(form),
            }).then((res) => res.json());
          },
        }}
      >
        <MagicForm>
          <form action="user">
            <input type="text" name="name" />
            <input type="text" name="email" />
            <button>Create user</button>
          </form>
        </MagicForm>
      </MagicFormProvider>
    </>
  );
}
```

## MagicForm is AtomicoJS project.

[**AtomicoJS?**](https://atomicojs.github.io/) Open source project for the creation of interfaces based on webcomponents, MagicForm was created with Atomico, a library of only 3kB that will allow you to create webcomponents with a functional approach, we invite you to learn more about Atomico and its tools that will improve your experience with webcomponents.

👐 I invite you to join the Atomicojs community and learn more about our projects! 👇

<table> 
<tr>
<td>


<a href="https://twitter.com/atomicojs"><img src="https://raw.githubusercontent.com/atomicojs/docs/master/.gitbook/assets/twitter.svg"/></a>

</td>
<td>


<a href="https://discord.gg/7z3rNhmkNE"><img src="https://raw.githubusercontent.com/atomicojs/docs/master/.gitbook/assets/discord.svg"/></a>

</td>
<td>

<a href="https://atomico.gitbook.io/doc/atomico/atomico-magic-form"><img src="https://raw.githubusercontent.com/atomicojs/docs/master/.gitbook/assets/doc-1.svg"/></a>

</td>
</tr>
</table>