Search code examples
javascriptmodal-dialogpopup

Add title & headers in popup modal in javascript


I'm trying somehow to create a popup modal for an editing function. However I'm having difficulties to add a simple title "Edit vote" and the headers of each fields to be edited. The functionality is working but I'm facing issues with "cosmetic" as I am beginner with js and css.

Here is the code I'm using to build popup modal classes:

{editVote && (
  <div className="edit-modal">
    <div className="modal-content">
      <h3>Edit Vote</h3>
      <div className="form-fields">
        {columns.map((column, index) => (
          <div key={index}>
            <label>{column}:</label>
            <span>{editVote[columnMappings[column]] || 'N/A'}</span>
          </div>
        ))}
      </div>
      <div className="input-fields">
        <label>First Name:</label>
        <input
          type="text"
          value={editedFields.first_name}
          onChange={(e) => handleFieldChange('first_name', e.target.value)}
        />
        <label>Last Name:</label>
        <input
          type="text"
          value={editedFields.last_name}
          onChange={(e) => handleFieldChange('last_name', e.target.value)}
        />
        <label>Gender:</label>
        <input
          type="text"
          value={editedFields.gender}
          onChange={(e) => handleFieldChange('gender', e.target.value)}
        />
        <label>Size:</label>
        <input
          type="number"
          value={editedFields.size}
          onChange={(e) => handleFieldChange('size', e.target.value)}
        />
        <label>Weight:</label>
        <input
          type="number"
          value={editedFields.weight}
          onChange={(e) => handleFieldChange('weight', e.target.value)}
        />
        <label>Birthday:</label>
        <input
          type="datetime-local"
          value={`${editedFields.birthday}T${editedFields.birthtime}`}
          onChange={(e) => handleFieldChange('birthday', e.target.value)}
        />
      </div>
      <div className="button-container">
        <button onClick={handleUpdateClick}>Update</button>
        <button onClick={() => setEditVote(null)}>Cancel</button>
      </div>
    </div>
  </div>
)}

For info, I have also put the colorMapping declaration to handle headers of the field:

const columnMappings: {
    Prénom: string;
    'Nom de famille': string;
    Sexe: string;
    'Taille(cm)': string;
    'Poids (kg)': string;
    Birthday: string;
}

Finally this is the different CSS I have created for each classes :

.edit-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5); /* Semi-transparent background */
  display: flex;
  justify-content: center;
  align-items: center;
}

.modal-content {
  background-color: white;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}

.modal-content h3 {
  margin-top: 0;
}

.form-fields {
  /* Style for the form fields section */
  margin-bottom: 20px;
}

.form-fields label {
  /* Style for field labels */
  display: block;
  font-weight: bold;
  margin-bottom: 5px;
}

.form-fields input {
  /* Style for input fields */
  width: 100%;
  padding: 8px;
  margin-bottom: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.input-fields {
  width: 100%;
  padding: 8px;
  margin-bottom: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.button-container {
  /* Style for the button container section */
  text-align: center;
}

.button-container button {
  /* Style for buttons */
  margin-right: 10px;
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.button-container button:hover {
  /* Style for button hover state */
  background-color: #0056b3;
}

In advance, many thanks !


Solution

  • I know that you already did the dialog and just needed a suggestion for the styling, but I couldn't help trying out the dialog element.

    That aside, I will suggest using flexbox to control the form fields and the labels. It is quite ... flexible and a nice way to align elements.

    window.addEventListener('click', e => {
      let href = e.target.attributes['href'];
      if(href && document.getElementById(href.value)){
        e.preventDefault();
        document.getElementById(href.value).showModal();
      }
    });
    
    document.forms.editvote.addEventListener('submit', e => {
      e.preventDefault();
      let submitter = e.submitter;
      // close the dialog parsing the name of the button clicked
      document.getElementById(e.target.name).close(submitter.name);
    });
    
    document.getElementById('editvote').addEventListener('close', e => {
      let form = document.forms[e.target.id];
      switch(e.target.returnValue) {
        case 'cancel':
          // clear the form
          form.reset();
          break;
        case 'update':
          // do something with the data
          let data = new FormData(form);
          console.log([...data]);
          break;
      }
    });
    body {
      font-family: sans-serif;
    }
    
    #editvote {
      border: gray solid thin;
      border-radius: 5px;
      box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    }
    
    #editvote::backdrop {
      background-color: AntiqueWhite;
      opacity: .8;
    }
    
    #editvote fieldset {
      border: none;
      padding: 0;
      margin: 0;
      display: flex;
      flex-direction: column;
      gap: .4em;
    }
    
    #editvote fieldset legend {
      margin-bottom: .5em;
      font-weight: bold;
      font-size: 110%;
    }
    
    #editvote fieldset label {
      display: flex;
      justify-content: space-between;
      gap: .4em;
    }
    
    #editvote fieldset label input {
      width: 300px;
    }
    <p><a href="editvote">Edit</a></p>
    <dialog id="editvote">
      <form name="editvote" method="dialog">
        <fieldset>
          <legend>Edit Vote</legend>
          <label>First Name:<input type="text" name="firstname" value="" /></label>
          <label>Last Name:<input type="text" name="lastname" value="" /></label>
          <label>Gender:<input type="text" name="gender" value="" /></label>
          <label>Size:<input type="number" name="size" value="" /></label>
          <label>Weight:<input type="number" name="weight" value="" /></label>
          <label>Birthday:<input type="datetime-local" name="birthday" value="" /></label>
          <div class="button-container">
            <button name="update">Update</button>
            <button name="cancel">Cancel</button>
          </div>
        </fieldset>
      </form>
    </dialog>