DEV Community

Skovhugger Lund
Skovhugger Lund

Posted on

Byg en enkel formular til træbeskæring med JavaScript

En kunde skriver: "Vi har et træ, der skal beskæres."

Det lyder som en enkel henvendelse. Men for virksomheden mangler der stadig flere oplysninger.

Hvor står træet? Hvilken type arbejde drejer det sig om? Hvad ønsker kunden at få ændret?

En digital formular kan hjælpe med at samle svarene.

I denne tutorial bygger vi en lille JavaScript-løsning til at kontrollere og organisere forespørgsler om træbeskæring.

Vi bruger almindelig HTML og JavaScript uden eksterne biblioteker.

Eksemplet handler om datahåndtering, ikke om at automatisere faglige beslutninger om træers sundhed eller sikkerhed.

1. Hvad skal formularen kunne?

Vi forestiller os en mindre træservicevirksomhed i Kolding.

Virksomheden modtager forespørgsler om blandt andet beskæring, kroneløft og vurdering af beskadigede træer.

Vores eksempel skal kunne:

  1. Registrere kundens område.
  2. Lade brugeren vælge en opgavetype.
  3. Modtage en kort beskrivelse.
  4. Kontrollere obligatoriske oplysninger.
  5. Oprette et struktureret JavaScript-objekt.
  6. Vise en bekræftelse uden at sende data til en server.

Vi gemmer ikke navn, adresse eller telefonnummer i denne demonstration.

Det gør eksemplet lettere at teste uden rigtige personoplysninger.

2. Start med en enkel HTML-formular

Opret filen index.html.

<!doctype html>
<html lang="da">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1">
  <title>Registrering af træopgave</title>
</head>
<body>
  <main>
    <h1>Beskriv din træopgave</h1>

    <form id="treeForm">
      <label for="area">Område</label>
      <select id="area" name="area" required>
        <option value="">Vælg område</option>
        <option value="Kolding">Kolding</option>
        <option value="Fredericia">Fredericia</option>
        <option value="Vejle">Vejle</option>
        <option value="Middelfart">Middelfart</option>
      </select>

      <label for="service">Opgavetype</label>
      <select id="service" name="service" required>
        <option value="">Vælg opgave</option>
        <option value="Beskæring">Beskæring</option>
        <option value="Kroneløft">Kroneløft</option>
        <option value="Vurdering">Faglig vurdering</option>
      </select>

      <label for="details">Beskrivelse</label>
      <textarea
        id="details"
        name="details"
        minlength="15"
        maxlength="1000"
        required
      ></textarea>

      <button type="submit">
        Kontrollér oplysninger
      </button>
    </form>

    <p id="feedback" role="status"
       aria-live="polite"></p>
  </main>

  <script src="app.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Formularen bruger almindelige HTML-felter.

required fortæller browseren, at et felt skal udfyldes.

minlength og maxlength begrænser længden af beskrivelsen.

aria-live="polite" gør det muligt for understøttede hjælpemidler at opfange ændringer i statusbeskeden.

Dette er en lille demonstration, ikke et færdigt tilgængelighedsdesign. En rigtig løsning bør også testes med tastatur og skærmlæser.

3. Beskriv data med et enkelt objekt

Når formularen bliver udfyldt, vil vi omsætte værdierne til et ensartet objekt.

Det kan eksempelvis se sådan ud:

const request = {
  area: "Kolding",
  service: "Beskæring",
  details: "En gren vokser tæt på terrassen.",
  status: "Afventer faglig vurdering"
};
Enter fullscreen mode Exit fullscreen mode

Bemærk feltet status.

Vi registrerer ikke, at træet er farligt, eller at en bestemt beskæringsmetode er korrekt.

Vi registrerer kun, at forespørgslen kræver faglig vurdering.

Det er en vigtig designbeslutning.

4. Valider oplysningerne med JavaScript

Opret nu filen app.js.

Vi starter med en funktion, der kontrollerer vores data.

const allowedAreas = new Set([
  "Kolding",
  "Fredericia",
  "Vejle",
  "Middelfart"
]);

const allowedServices = new Set([
  "Beskæring",
  "Kroneløft",
  "Vurdering"
]);

function validateRequest(request) {
  const errors = [];

  if (!allowedAreas.has(request.area)) {
    errors.push("Vælg et gyldigt område.");
  }

  if (!allowedServices.has(request.service)) {
    errors.push("Vælg en gyldig opgavetype.");
  }

  if (
    typeof request.details !== "string" ||
    request.details.trim().length < 15
  ) {
    errors.push(
      "Beskrivelsen skal være mindst 15 tegn."
    );
  }

  if (
    typeof request.details === "string" &&
    request.details.length > 1000
  ) {
    errors.push(
      "Beskrivelsen må højst være 1000 tegn."
    );
  }

  return {
    valid: errors.length === 0,
    errors
  };
}
Enter fullscreen mode Exit fullscreen mode

Vi bruger Set, fordi vi ønsker at kontrollere, om en værdi findes på en liste over tilladte muligheder.

Det er enklere end at skrive mange individuelle betingelser.

Funktionen returnerer både et resultat og eventuelle fejl.

Den kan derfor bruges af en formular, en test eller en fremtidig API-integration.

5. Håndtér formularens submit-event

Nu skal vi forbinde HTML og JavaScript.

Tilføj dette nederst i app.js:

const form = document.querySelector("#treeForm");
const feedback = document.querySelector("#feedback");

form.addEventListener("submit", (event) => {
  event.preventDefault();

  const formData = new FormData(form);

  const request = {
    area: String(formData.get("area") ?? ""),
    service: String(formData.get("service") ?? ""),
    details: String(
      formData.get("details") ?? ""
    ).trim(),
    status: "Afventer faglig vurdering"
  };

  const result = validateRequest(request);

  if (!result.valid) {
    feedback.textContent =
      result.errors.join(" ");
    return;
  }

  feedback.textContent =
    "Oplysningerne er kontrolleret. " +
    "De er ikke blevet sendt eller gemt.";

  // Her kan en rigtig applikation senere
  // integreres med en sikker backend.
});
Enter fullscreen mode Exit fullscreen mode

event.preventDefault() forhindrer formularens normale indsendelse.

Vi bruger FormData til at hente værdierne.

Dernæst kalder vi valideringsfunktionen.

Hvis oplysningerne er gyldige, viser programmet en bekræftelse.

Der bliver ikke sendt nogen oplysninger til en server.

Derfor skal denne demonstration heller ikke beskrives som et fungerende bookingsystem.

6. Test valideringen

En god formular skal ikke kun virke, når brugeren gør alt korrekt.

Den skal også håndtere fejl.

Vi kan teste funktionen direkte i browserens konsol.

const testRequest = {
  area: "Kolding",
  service: "Beskæring",
  details: "Kort",
  status: "Afventer faglig vurdering"
};

console.log(validateRequest(testRequest));
Enter fullscreen mode Exit fullscreen mode

Resultatet bliver:

{
  valid: false,
  errors: [
    "Beskrivelsen skal være mindst 15 tegn."
  ]
}
Enter fullscreen mode Exit fullscreen mode

Ændr derefter beskrivelsen:

testRequest.details =
  "En gren hænger lavt over indkørslen.";

console.log(validateRequest(testRequest));
Enter fullscreen mode Exit fullscreen mode

Nu bliver resultatet:

{
  valid: true,
  errors: []
}
Enter fullscreen mode Exit fullscreen mode

Vi har dermed en grundlæggende kontrol, som også kan testes uden at udfylde formularen manuelt.

7. Gør fejlbeskederne nyttige

En god fejlbesked fortæller brugeren, hvad der skal ændres.

Sammenlign disse to beskeder.

Uklar besked:

Ugyldige data.

Mere hjælpsom besked:

Beskrivelsen skal være mindst 15 tegn.

Den sidste besked gør det lettere at rette fejlen.

I en større løsning kan man også vise fejlbeskeder ved de enkelte felter og sørge for korrekt tilknytning med aria-describedby.

Man bør ikke kun bruge farver til at vise fejl.

Teksten skal også forklare problemet.

8. Hvorfor bør vi ikke beregne træets risiko automatisk?

Forestil dig, at en bruger skriver:

"Træet hælder mod huset."

Det kan være en vigtig observation.

Men teksten fortæller ikke, om træet er ustabilt.

Et træ kan have vokset med en naturlig hældning i mange år.

Et andet træ kan have ændret hældning pludseligt på grund af problemer omkring rødderne.

Forskellen kan være meget vigtig.

Derfor bør en simpel formular ikke omsætte bestemte ord til konklusioner som:

  • Træet er sikkert.
  • Træet er farligt.
  • Træet skal fældes.
  • En bestemt gren skal fjernes.

Det kræver en faglig vurdering af de konkrete forhold.

Software kan indsamle observationer. Det betyder ikke, at softwaren kan vurdere træets stabilitet.

Ved mistanke om akut fare bør brugeren heller ikke være afhængig af en almindelig onlineformular. En virkelig løsning skal tydeligt oplyse, hvordan sådanne situationer håndteres.

9. Hvad med databeskyttelse?

Vores demonstration bruger kun område, opgavetype og beskrivelse.

Men et frit tekstfelt kan stadig indeholde personoplysninger.

En bruger kan eksempelvis skrive en privat adresse eller et telefonnummer i beskrivelsen.

Derfor bør man ikke automatisk logge eller offentliggøre formularens indhold.

Hvis løsningen senere skal håndtere rigtige henvendelser, bliver der behov for flere overvejelser:

  • Sikker overførsel med HTTPS
  • Serverbaseret validering
  • Passende adgangskontrol
  • Begrænset opbevaring af personoplysninger
  • Retningslinjer for sletning
  • Et relevant behandlingsgrundlag

Browserbaseret validering er nyttig for brugeroplevelsen, men den kan omgås.

En backend skal derfor altid validere oplysningerne igen.

10. Den virkelige kontekst: Træbeskæring i Kolding

En træservicevirksomhed kan modtage meget forskellige henvendelser.

En kunde ønsker måske fri passage under et træ. En anden vil have vurderet en beskadiget gren.

Det er ikke nødvendigvis samme type opgave.

Skovhugger Lund er en træservicevirksomhed med base i Kolding. Virksomheden tilbyder blandt andet kroneløft, beskæring ved klatring og beskæring fra lift.

På virksomhedens side om beskæring af træer i Kolding kan man læse om arbejdet og de faglige hensyn, som indgår i professionel træpleje.

Det gør branchen til et godt eksempel på, hvorfor software skal skelne mellem en kundes beskrivelse og en professionel vurdering.

En formular kan hjælpe med at samle oplysninger.

Men den kan ikke alene fastlægge beskæringsmetode, pris eller sikkerhed.

Dette tutorial er et selvstændigt softwareeksempel. Det er ikke en beskrivelse af Skovhugger Lunds faktiske interne systemer.

11. Hvad kunne være næste udviklingstrin?

Hvis vi skulle videreudvikle løsningen, ville jeg prioritere tre forbedringer.

A. Bedre tilgængelighed

Felterne skal være lette at bruge med tastatur og skærmlæser.

Det er også vigtigt at teste fejlbeskeder og fokusstyring.

B. En sikker backend

En rigtig løsning skal have servervalidering, adgangskontrol og en gennemtænkt håndtering af data.

C. En tydelig arbejdsgang

En forespørgsel bør kunne bevæge sig gennem administrative statusser som:

Modtaget
    |
    v
Afventer faglig vurdering
    |
    v
Tilbud under udarbejdelse
    |
    v
Afsluttet
Enter fullscreen mode Exit fullscreen mode

Det er administrative trin.

De siger ikke noget om, hvorvidt træet er sikkert, eller om en bestemt arbejdsmetode er forsvarlig.

Afslutning

Vi har bygget en lille HTML- og JavaScript-formular, som kan indsamle, kontrollere og strukturere oplysninger om træopgaver.

Løsningen bruger ingen eksterne biblioteker.

Den er enkel at forstå og kan testes direkte i browseren.

Det vigtigste er dog ikke mængden af kode.

Det er grænsen mellem det, programmet ved, og det, et menneske skal vurdere.

God software hjælper med at organisere arbejdet.

Den foregiver ikke at have faglig viden, som ikke findes i dataene.

Top comments (0)