Un formulari pemet recollir dades de l'usuari i enviar-les a un servidor

Introducció

Un formulari és un document que té espais per recollir informació.

A diferència d'un formulari en paper, un formulari HTML té un botó que envia les dades a un servidor.

Entorn de treball

A continuació executarem un servidor TypeScript en entorn local per tal de poder provar que els nostres formularis funcinonen correctament.

Instal.la node amb Scoop:

> scoop install nodejs

Baixa el projecte https://gitlab.com/xtec/web/form:

> git clone https://gitlab.com/xtec/web/form
> cd form

Instal.la les dependències de l'aplicació:

> npm install

added 65 packages, and audited 66 packages in 1s

13 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Arrenca el servidor web:

> npm run dev
Listening on http://localhost

Obre el navegador a http://localhost

A la pàgina "home" hi ha un formulari.

Omple les dades del formulari i apreta el botó enviar:

El navegador enviar les dades a la URL /form.

El servidor executa aquesta secció de codi del fitxer src/main.ts:

app.get('/form', (req: Request, res: Response) => {
  res.render("form", { title: "GET", params: req.query })
})

El servidor crea un document web amb una taula on estan totes les dades que ha rebut, que estan en la propietat req.query, i retona un document HTML:

Formulari

Obre el projecte amb VS Code.

A la carpeta public es on està el document index.htmlamb el formulari de la pàgina / o "home".

Un formulari es declara amb l'element <form>:

<form action="/form">

</form>

Action

L'atribut action de l'element form indica la URL a la que s'ha d'enviar el formulari.

Si no declares l'atribut, el formulari s'envia amb el mètode HTTP GET, i les dades s'afegeixen al final de la URL a continuació de ?.

Si et fixes en la URL, pots veure les dades del formulari que has omplert:

Com has vist abans, aquesta sol.licitut la processa el mètode app.get('/form',...) del fitxer src/main.ts.

Normalment el mètode GET es fa servir en formularis petits, o quan vols que el servidor t'envii dades.

En tots els altres casos, com es pujar un fitxer, dades sensibles, etc., és millor utilitzar el mètode POST que incorpora les dades en el camp body de la sol.licitut.

Modifica el fitxer index.html i indica que el mètode és POST:

<form action="/form" method="POST">

</form>

Ara la sol.licitut la processa el mètode app.post('/form',...) del fitxer src/main.ts.

Input

Un formulari està format per un o més camps, on cada camp té un name que identifica la dada, i un botó per fer clic i enviar les dades al servidor :

<form action="/form" method="POST">
    <input type="text" name="nom"/>
    <button type="submit">Envia</button>
</form>

Modifica el fitxer index.html i afegeix el camp cognom i telefon:

<form action="/form" method="POST">
    <input type="text" name="nom"/>
    <input type="text" name="cognom"/>
    <input type="text" name="telefon"/>
    <button type="submit">Envia</button>
</form>

Omple el formulari i envia les dades al servidor:

Però potser l'usuari vol saber que ha de posar en cada camp ...

Doncs posa un element <label> al costat d'un element <input>:

<form action="/form" method="POST">
    <label>Nom</label>
    <input type="text" name="nom"/>
    <button type="submit">Envia</button>
</form>

Però millor si associes el <label> amb l'<input>: afegeix un atribut id a l'element <input>, i un atribut for a l'element <label> amb la id de l'element <input>.

<form action="/form" method="POST">
    <label for="nom">Nom</label>
    <input type="text" id="nom" name="nom"/>
    <button type="submit">Envia</button>
</form>

D'aquesta manera, si fas clic a l'etiqueta, l'input agafa el focus de l'entrada de text.

Però si vols estilitzar un formulari, has d'afegir classes de Bootstrap:

<form action="/form" methos="post">
    <div class="mb-3">
        <label for="nom" class="form-label">Nom</label>
        <input type="text" class="form-control" id="nom" name="nom">
    </div>
    <div class="mb-3">
        <label for="cognom" class="form-label">Cognom</label>
        <input type="text" class="form-control" id="cognom" name="cognom">
    </div>
    <div class="mb-3">
        <label for="telefon" class="form-label">Telefon</label>
        <input type="text" class="form-control" id="telefon" name="telefon">
    </div>
     <button type="submit" class="btn btn-primary">Envia</button>
</form>

Input

L'element <input> és fa servir per recollir una dada simple que pot ser de tipus diferents.

L'atribut type indica quin tipus de dada s'espera i el navegador visualitza l'element de manera diferent i valida la dada que l'usuari entra.

Fins ara has utlitzat el tipus neutre text:

<form action="/form" method="POST">
    <label>Nom</label>
    <input type="text" name="nom"/>
    <button type="submit">Envia</button>
</form>

Per exemple, pots utilizar el tipus email o password tal com es mostra a continuació:

Pots veure que:

  1. Si no introdueixes un email en format correcte no et deixa enviarel formulari.
  2. La contrassenya no es visualitza.
<form action="/form" method="post">
  <div class="mb-3">
    <label for="email" class="form-label">Email address</label>
    <input type="email" class="form-control" id="email" name="email">
  </div>
  <div class="mb-3">
    <label for="password" class="form-label">Password</label>
    <input type="password" class="form-control" id="password" name="password">
  </div>
  <button type="submit">Envia</button>
</form>

Altres tipus són: color, date, month, number, range, tel, time, url o week.

Text Area

L'element <textarea> s'utilitza per crear una entrada de text de diverses línies, i ha de tenir una etiqueta d'obertura i una de tancament.

<form action="/form" method="post" class="m-3">
    <textarea class="form-control" name="text" rows=5>Cowards die many times before their deaths; the valiant never taste of death but once</textarea>
    <button type="submit" class="btn btn-primary mt-3">Envia</button>
</form>

Qualsevol text que apareix entre les etiquetes d'obertura <textarea>, i de tancament </textarea>, apareix al quadre de text quan es carregua la pàgina.

L'atribut rows indica quantes files s'han de visualitzar, que equival a dir quin espai vertical ha d'ocupar l'element <textarea>.

Opcions

Alguns cops l'usuari ha d'escollir entre vàries opcions.

Radio Button

Si l'usuari només pot escollir una opció, es fa servir un conjunt d'elements <input> de tipus radio.

Si fas clic a un botó, aquest queda seleccionat, però si fas clic a un altre botó aquest queda selecciont i l'altre deixar d'estar seleccionat, tal com passava en les radios dels cotxes antics:

El navegador sap que tots aquests elements <input> de tipus radio estan relacionats perqué el valor de l'atribut name és el mateix:

<form action="/form" method="post" class="m-3">
   <div class="form-check">
       <input class="form-check-input" type="radio" name="music" value="rock" id="music-rock">
       <label class="form-check-label" for="music-rock">Rock</label>
   </div>
   <div class="form-check">
       <input class="form-check-input" type="radio" name="music" value="pop" id="music-pop" checked>
       <label class="form-check-label" for="music-pop">Pop</label>
   </div>
   <button type="submit" class="btn btn-primary mt-2">Envia</button>
</form>

I com que l'usuari no ha d'introduïr cap dada, tots els elements <input> tenen l'atribut value que és el que s'envia al servidor.

Si vols que sempre hi hagi un valor seleccionat per defecte, un dels elements <input> ha de tenir l'atribut checked.

Per saber més: https://uxplanet.org/radio-buttons-ux-design-588e5c0a50dc

Checkbox

Un "checkbox" es fa servir quan l'usuari ha de poder seleccionar més d'un element:

Please select your favorite music service(s):

En aquest cas, l'<input> és de tipus checkbox i, igual que amb el elements de tipus radio, han de tenir el mateix valor per l'atribut name.

<form action="form" method="post">
   <p>Please select your favorite music service(s):</p>
    <div class="form-check">
        <input class="form-check-input" type="checkbox" name="service" value="itunes" id="service-itunes">
        <label class="form-check-label" for="service-itunes">iTunes</label>
    </div>
    <div class="form-check">
        <input class="form-check-input" type="checkbox" name="service" value="spotify" id="service-spotify">
        <label class="form-check-label" for="service-spotify">Spotify</label>
    </div>
    <button type="submit" class="btn btn-primary mt-3">Envia</button>
</form>

select

Enlloc d'utlitzar els elements <input> de "type" radio i checkbox, pots utilitzar l'element <select>, que mostra les diferents opcions en una llista que es desplega, i és molt útil quan hi ha moltes opcions disponibles i vols que ocupi el mínimm espai.

L'element <select> té l'atriburt name, i està format per un conjunt d'elements <option> que tenen l'atribut value corresponent.

<form action="/form" method="post">
   <label for="select-cars">Escull un cotxe:</label>
   <select id="select-cars" class="form-select mt-3" name="car">
      <option selected value="volvo">Volvo</option>
      <option value="saab">Saab</option>
      <option value="opel">Opel</option>
      <option value="audi">Audi</option>
    </select>
    <button type="submit" class="btn btn-primary mt-3">Submit</button>
</form>

Amb l'atribut selected pots seleccionar quina opció s'utlitza per defecte.

Si no indiques cap, els navegadors envien la primera de la llista.

Selecció multiple

Si vols permetre que l'usuari seleccioni més d'una opció, has d'utlitzar l'atribut mutltiple en l'element select.

Has de mantenir la tecla Ctrl apretada per seleccionar més d'un valor:

<form action="/form" method="post">
    <label for="select-languages">Quins idiomes parles:</label>
    <select id="select-languages" class="form-select" name="languages" multiple>
        <option value="english">Anglès</option>
        <option value="arabic">Àrab</option>
        <option value="castellà">Castellà</option>
        <option value="catalan">Català</option>
        <option value="french">Francés</option>
    </select>
    <button type="submit" class="btn btn-primary mt-3">Envia</button>
</form>

Fitxer

<form action="/form" method="post">
  <label for="file-song" class="form-check-label">Puja una cançó:</label>
  <input type="file" id="file-song" class="form-control mt-3" name="song" />
  <button type="submit" class="btn btn-primary mt-3">Upload</button>
</form>

Si voleu permetre que els usuaris pugin un fitxer (per exemple, una imatge, un vídeo, un mp3 o un PDF), haureu d'utilitzar un quadre d'entrada de fitxer.

Activitats

1.- La millor manera d'apendre un cop ja saps els fonament, es mirar, seleccionar, copiar i adaptar.

En aquests document tens uns quants exemples: Boostrap 5 forms.

2.- Escriu aquest formulari

Fulla de l'aventurer

Informació

Nom
Raça
Altura

Característiques

Nivell

Habilitats

<div class="container p-3">
    <h1 class="fs-3 text-center text-success">Fulla de l'aventurer</h1>
    <form action="/form" class="border border-3 rounded p-2">
        <div class="border border-2 rounded p-2 bg-primary">
            <p class="fw-bold text-white">Informació</p>
            <div class="input-group mb-3">
                <span class="input-group-text" id="basic-addon1">Nom</span>
                <input type="text" class="form-control" />
            </div>
            <div class="input-group mb-3">
                <span class="input-group-text">Raça</span>
                <select class="form-select">
                    <option selected value="1">Elf</option>
                    <option value="2">Nan</option>
                    <option value="3">Home</option>
                </select>
            </div>
            <div class="input-group mb-3">
                <span class="input-group-text" id="basic-addon1">Altura</span>
                <input type="number" class="form-control" placeholder="en cms" />
            </div>
            <div class="mb-3">
                <label class="form-label">Equipament:</label>
                <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"
                    placeholder="Armes, motxilles i altres possesions"></textarea>
            </div>
        </div>

        <div class="border border-2 rounded p-2 bg-info mt-3">
            <p class="fw-bold text-white">Característiques</p>
            <div>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio1"
                        value="option1" />
                    <label class="form-check-label" for="inlineRadio1">Destreça</label>
                </div>

                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2"
                        value="option2" />
                    <label class="form-check-label" for="inlineRadio2">Força</label>
                </div>

                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio3"
                        value="option3" />
                    <label class="form-check-label" for="inlineRadio3">Intell.ligència</label>
                </div>
            </div>
            <div class="input-group mt-3">
                <span class="input-group-text">Nivell</span>
                <select class="form-select">
                    <option selected value="1">Obligatori</option>
                    <option value="2">Opcional</option>
                </select>
            </div>

        </div>

        <div class="border border-2 rounded p-2 bg-info mt-3">
            <p class="fw-bold text-white">Habilitats</p>
            <div>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="checkbox" name="habilitats" value="agilitat" />
                    <label class="form-check-label">Agilitat</label>
                </div>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="checkbox" name="habilitats" value="coneixement" />
                    <label class="form-check-label">Coneixement</label>
                </div>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="checkbox" name="habilitats" value="manipulació" />
                    <label class="form-check-label">Manipulació</label>
                </div>
                <div class="form-check form-check-inline">
                    <input class="form-check-input" type="checkbox" name="habilitats" value="percepció" />
                    <label class="form-check-label">Percepció</label>
                </div>
            </div>
        </div>

        <div class="d-grid gap-2 d-md-block mt-3 ">

            <button type="submit" class="btn btn-primary">Jugar</button>
            <button type="submit" class="btn btn-danger">Cancelar</button>
        </div>
    </form>
</div>