Maison > interface Web > js tutoriel > le corps du texte

Création d'un formulaire de commentaires utilisateur avec Perseid et React

DDD
Libérer: 2024-09-19 03:45:06
original
986 Les gens l'ont consulté

Dans ce guide, nous expliquerons la création d'un formulaire de commentaires utilisateur dynamique à l'aide de la bibliothèque @perseid/form, une alternative puissante à Formik et React Hook Form. Vous verrez comment @perseid/form facilite la gestion de l'état, de la validation et du rendu conditionnel du formulaire. Le formulaire que nous allons créer demandera aux utilisateurs d'évaluer un service et de fournir des commentaires. En fonction de la note, il affichera un message de « remerciement » ou invitera l'utilisateur à fournir des commentaires supplémentaires.

? Commençons !


Étape 1 : Configuration de la configuration du formulaire

La première étape consiste à définir la configuration du formulaire. Cette configuration décrit le comportement du formulaire, y compris les champs, les étapes et le flux entre eux. Ici, nous allons créer des champs pour une note et un avis, avec une logique conditionnelle basée sur la note de l'utilisateur. Nous définirons également des messages pour les commentaires positifs et négatifs.

Voici le code de configuration :

import { type Configuration } from "@perseid/form";

const formConfiguration: Configuration = {
  // Root step-the form will start from there.
  root: "feedback",
  // Callback triggered on form submission.
  onSubmit(data) {
    alert(`Submitting the following JSON: ${JSON.stringify(data)}`);
    return Promise.resolve();
  },
  // `fields` define the data model the form is going to deal with.
  // Expect the submitted data JSON to match this schema.
  fields: {
    rating: {
      type: "integer",
      required: true,
    },
    review: {
      type: "string",
      required: true,
      // Display this field only if condition is met...
      condition: (inputs) =>
        inputs.rating !== null && (inputs.rating as number) < 3,
    },
    // Type `null` means that the value of this field will not be included in submitted data.
    submit: {
      type: "null",
      submit: true,
    },
    message_good: {
      type: "null",
    },
    message_bad: {
      type: "null",
    },
  },
  // Now that fields are defined, you can organize them in a single or multiple steps,
  // depending on the UI you want to build!
  steps: {
    feedback: {
      fields: ["rating", "review", "submit"],
      // Whether to submit the form at the end of this step.
      submit: true,
      // Next step is conditionned to previous user inputs...
      nextStep: (inputs) =>
        (inputs.rating as number) < 3 ? "thanks_bad" : "thanks_good",
    },
    thanks_good: {
      fields: ["message_good"],
    },
    thanks_bad: {
      fields: ["message_bad"],
    },
  },
};

Copier après la connexion

Dans cette configuration :

  • Le formulaire commence à l'étape de commentaires.
  • Le formulaire contient deux champs : note (obligatoire) et avis (facultatif sauf si la note est inférieure à 3).
  • En fonction de l'évaluation, le formulaire accède au message de retour « bon » ou « mauvais ».
  • Lors de la soumission du formulaire, une simple alerte est déclenchée avec les données soumises.

Le point clé à comprendre ici est la fonction de la propriété field. Il définit la structure des données qui seront soumises, agissant essentiellement comme un modèle de données. En revanche, la propriété steps décrit le flux du formulaire, déterminant comment ces champs seront présentés à l'utilisateur.


Étape 2 : Création des composants React du formulaire

Maintenant que nous avons la configuration, il est temps de créer l'interface utilisateur réelle qui restituera le formulaire. En utilisant @perseid/form/react, nous pouvons créer des composants de champ personnalisés pour gérer les interactions des utilisateurs pour chaque partie du formulaire.

Voici le composant principal de React :

import React from "react";
import Form, { type FormFieldProps } from "@perseid/form/react";

// The actual React component, used to build the UI!
function Field(props: FormFieldProps): JSX.Element {
  const { path, engine, value, status } = props;
  const [currentRating, setCurrentRating] = React.useState(0);

  // Display a different element depending on the field...

  if (path === "thanks_good.1.message_good") {
    return (
      <div className="message">
        <h1>Thanks for the feedback ?</h1>
        <p>We are glad you enjoyed!</p>
      </div>
    );
  }

  if (path === "thanks_bad.1.message_bad") {
    return (
      <div className="message">
        <h1>We're sorry to hear that ?</h1>
        <p>We'll do better next time, promise!</p>
      </div>
    );
  }

  if (path === "feedback.0.rating") {
    return (
      // Depending on the field status, define some extra classes for styling...
      <div
        className={`rating ${status === "error" ? "rating--error" : ""}`}
        onMouseLeave={() => {
          setCurrentRating((value as number | null) ?? 0);
        }}
      >
        <h1>How would you rate our service?</h1>
        {[1, 2, 3, 4, 5].map((rating) => (
          <span
            key={rating}
            className={`rating__star ${
              currentRating >= rating ? "rating__star--active" : ""
            }`}
            onMouseEnter={() => {
              setCurrentRating(rating);
            }}
            onClick={() => {
              // On click, notify the form engine about new user input.
              engine.userAction({ type: "input", path, data: rating });
            }}
          ></span>
        ))}
      </div>
    );
  }

  if (path === "feedback.0.review") {
    return (
      <div className={`review ${status === "error" ? "review--error" : ""}`}>
        <label>Could you tell us more?</label>
        <textarea
          onChange={(e) =>
            engine.userAction({ type: "input", path, data: e.target.value })
          }
        />
      </div>
    );
  }

  // path === 'feedback.0.submit'
  return (
    <button
      className="submit"
      onClick={() => {
        engine.userAction({ type: "input", path, data: true });
      }}
    >
      Submit
    </button>
  );
}
Copier après la connexion

Ici, le composant Field utilise la prop path pour décider quoi rendre :

  • Un composant de notation où les utilisateurs peuvent sélectionner une note par étoiles.
  • Une zone de texte permettant aux utilisateurs de fournir des commentaires supplémentaires.

Messages « Merci » qui apparaissent en fonction de la note. Le formulaire ajustera dynamiquement ses champs et ses étapes en fonction des saisies de l'utilisateur.

Plutôt cool, non ?

Building a User Feedback Form with Perseid and React


Étape 3 : Exécuter l'application

Maintenant que notre configuration de formulaire et notre composant sont prêts, intégrons-les dans une application React de base. Voici le code pour initialiser et restituer le formulaire :

import { createRoot, type Root } from "react-dom/client";

// Let's run the app!
let app: Root;

// Creating React root...
const container = document.querySelector("#root") as unknown as HTMLElement;
app = createRoot(container);
app.render(
  // Router is the main component for any Perseid app.
  <Form Field={Field} configuration={formConfiguration} />
);
Copier après la connexion

Ce code monte le formulaire sur le DOM à l'aide de l'API createRoot de React. Le composant Form, qui connecte notre configuration et notre composant Field, gère tout le reste.

Étape 4 : Ajout de styles

Très bien, nous avons notre logique d'application, mais si vous exécutez le code maintenant, vous verrez que c'est un peu... brut ?

Building a User Feedback Form with Perseid and React

Alors, embellissons le formulaire en ajoutant quelques styles et animations ! Vous trouverez ci-dessous une feuille de style simple qui la rend beaucoup plus attrayante :

// A few animations for fun...

@keyframes swipe-out {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  75% {
    opacity: 0;
    transform: translateX(-100%);
  }
  100% {
    opacity: 0;
    transform: translateX(-100%);
  }
}

@keyframes swipe-in-one {
  0% {
    opacity: 0;
    transform: translateX(100%);
  }
  75% {
    transform: translateX(0);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes swipe-in-two {
  0% {
    opacity: 0;
    transform: translateX(0);
  }
  75% {
    transform: translateX(-100%);
  }
  100% {
    opacity: 1;
    transform: translateX(-100%);
  }
}

@keyframes bubble-in {
  0% {
    transform: scale(0.5);
  }
  75% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes fade-in {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

// Some global basic styling...

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  display: grid;
  height: 100vh;
  color: #aaaaaa;
  align-items: center;
  font-family: "Helvetica", sans-serif;
}

// And form-specific styling.

.perseid-form {
  width: 100%;
  margin: auto;

  &__steps {
    display: flex;
    overflow: hidden;
  }

  &__step {
    min-width: 100%;
    padding: 1rem 3rem;
    animation: 500ms ease-in-out forwards swipe-out;

    &__fields {
      display: grid;
      row-gap: 2rem;
    }
  }

  &__step[class*="active"]:first-child {
    animation: 500ms ease-in-out forwards swipe-in-one;
  }
  &__step[class*="active"]:last-child:not(:first-child) {
    animation: 500ms ease-in-out forwards swipe-in-two;
  }
}

.submit {
  border: none;
  cursor: pointer;
  padding: 1rem 2rem;
  border-radius: 8px;
  color: #fefefe;
  font-size: 1.25rem;
  background: #46c0b0;
  justify-self: flex-end;
  transition: all 250ms ease-in-out;

  &:hover {
    background: #4cccbb;
  }
}

.rating {
  position: relative;
  padding: 0.25rem 0;

  &__star {
    cursor: pointer;
    display: inline-block;
    font-size: 2rem;
    min-width: 2rem;
    min-height: 2rem;

    &::after {
      content: "⚪️";
    }

    &--active {
      animation: 250ms ease-in-out forwards bubble-in;
      &::after {
        content: "?";
      }
    }
  }

  &[class*="error"] {
    &::after {
      left: 0;
      bottom: -1.5rem;
      color: #f13232;
      position: absolute;
      font-size: 0.75rem;
      content: "? This field is required";
      animation: 250ms ease-in-out forwards fade-in;
    }
  }
}

.review {
  display: grid;
  row-gap: 1rem;
  position: relative;
  animation: 250ms ease-in-out forwards fade-in;

  label {
    font-size: 1.25rem;
  }

  textarea {
    resize: none;
    min-height: 5rem;
    border-radius: 8px;
    border: 1px solid #46c0b0;
    transition: all 250ms ease-in-out;
  }

  &[class*="error"] {
    &::after {
      left: 0;
      bottom: -1.5rem;
      color: #f13232;
      position: absolute;
      font-size: 0.75rem;
      content: "? This field is required";
      animation: 250ms ease-in-out forwards fade-in;
    }
  }
}

@media screen and (min-width: 30rem) {
  .perseid-form {
    max-width: 30rem;
  }
}
Copier après la connexion

Et voilà ?


Conclusion

Félicitations ! ? Vous venez de créer un formulaire de commentaires utilisateur dynamique avec Perseid et React.

Dans ce tutoriel, nous avons expliqué comment :

  • Définissez une configuration de formulaire avec une logique conditionnelle.
  • Créez des composants React personnalisés pour gérer les interactions des utilisateurs.
  • Rendez le formulaire dans votre application et stylisez-le avec des animations et du CSS personnalisé.

N'hésitez pas à expérimenter des champs et des étapes supplémentaires en fonction de votre cas d'utilisation. Amusez-vous à créer des formulaires géniaux ! ?


  • ? Plus d'exemples
  • ✅Documentation complète
  • ? Rejoignez notre Discord
  • ? Star le projet sur GitHub
  • ❤️ Parrainez Perséide

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!