skip to Main Content

I’m trying to create this form page. I already have a form ready for data insertion to database. I just need to stylize it so that the form changes dynamically after selection change.

I’m trying to create it dynamic so that when you select something else, the previous fieldset changes to new one and the last selection disappears. Nothing works with my code. I tried traditional JS – same results. I already put the div as display:none in CSS. Maybe my syntax is wrong?

$('body').on('change', '##productType', function() {
  if ($(this).val() == "DVD")
    $("#DVD").show();
  else
    $("#DVD").hide();
});
<form>
  <fieldset>
    <label for="#productType">Type Switcher</label>
    <select id="#productType">
      <option>--Select a Type</option>
      <option value="DVD" id="#DVD" onchange="show(this)">DVD</option>
      <option value="Book" id="#Book" onchange="show(this)">Book</option>
      <option value="Furniture" id="#Furniture" onchange="show(this)">Furniture</option>
    </select>
  </fieldset>

  <br>
  <div class="subform-test-class">
    <fieldset id="#DVD" class="info-block">
      <label for="#DVD">Size (MB)</label>
      <input type="text" id="#DVD" name="dvdSize">
      <p>*Please provide size of the DVD (MB)</p>
    </fieldset>
    <br>
    <fieldset id="#Book" class="info-block">
      <label for="#weight" id="book">Weight (KG)</label>
      <input type="text" id="#weight" name="bookWeight">
      <p>*Please provide weight of the book in KG.</p>
    </fieldset>
    <br>

    <fieldset id="#Furniture" class="info-block">
      <label for="#height" id="height">Height</label>
      <input type="text" id="#height" name="fHeight">

      <label for="#width" id="width">Width</label>
      <input type="text" id="#width" name="fWidth">

      <label for="#length" id="length">Length</label>
      <input type="text" id="#length" name="fLength">
      <p>*Please provide size of the furniture in dimensions of HxWxL</p>
    </fieldset>
  </div>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

2

Answers


  1. There are many mistakes in your code:-

    1. For selecting an item through Id, you should use single hash #.
    2. Id should be unique in the page and you have given too much same ID’s throughout the code.
    3. For giving id to the element, don’t write # with the id in the html. For example:- the id for the DVD field can be id="DVD" instead of id="#DVD".

    There are some other minor errors also, but you will figure it out by looking at the updated code. Here is the updated code:-

    $('body').on('change', '#productType', function() {
      if ($(this).val() == "DVD")
        $("#DVD_fieldset").show();
      else
        $("#DVD_fieldset").hide();
    });
    #DVD_fieldset{
     display: none;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <form>
      <fieldset>
        <label for="productType">Type Switcher</label>
        <select id="productType">
          <option>--Select a Type</option>
          <option value="DVD" onchange="show(this)">DVD</option>
          <option value="Book" onchange="show(this)">Book</option>
          <option value="Furniture" onchange="show(this)">Furniture</option>
        </select>
      </fieldset>
    
      <br>
      <div class="subform-test-class">
        <fieldset id="DVD_fieldset" class="info-block">
          <label for="DVD">Size (MB)</label>
          <input type="text" id="DVD" name="dvdSize">
          <p>*Please provide size of the DVD (MB)</p>
        </fieldset>
        <br>
        <fieldset id="weight_fieldset" class="info-block">
          <label for="weight" id="book">Weight (KG)</label>
          <input type="text" id="weight" name="bookWeight">
          <p>*Please provide weight of the book in KG.</p>
        </fieldset>
        <br>
    
        <fieldset id="Furniture" class="info-block">
          <label for="height" id="height">Height</label>
          <input type="text" id="height" name="fHeight">
    
          <label for="width">Width</label>
          <input type="text" id="width" name="fWidth">
    
          <label for="length">Length</label>
          <input type="text" id="length" name="fLength">
          <p>*Please provide size of the furniture in dimensions of HxWxL</p>
        </fieldset>
      </div>
    </form>
    Login or Signup to reply.
  2. There are different ways to achieve your desired outcome, the first of which – with explanatory comments in the code – is below:

    // using a named function to handle the show/hide functionality, this function
    // takes one argument - 'evt', a reference to the event that this function
    // is to handle - and is passed automatically from the (later) use of
    // EventTarget.addEventListener():
    const showOnChoice = (evt) => {
      // here we use destructuring assignment, retrieving the
      // currentTarget property-value from the currentTarget
      // property of the Event-Object ('evt'); the currentTarget
      // is the element to which this function was bound:
      let {
        currentTarget
      } = evt, {
        // again using destructuring assignment, this time
        // to assign the value of the currentTarget element
        // to the variable of 'value':
        value
      } = currentTarget,
      // here we retrieve the element that we wish to show,
      // using document.querySelector() - along with a
      // template-literal, to interpolate the value variable
      // into the selector string - this retrieves the first
      // matching element in the document (it may return null
      // if there is no matching element, so consider sanity-
      // checks to verify its existence in production):
      toShow = document.querySelector(`.info-block.${value}`),
        // here we retrieve all elements that match the
        // supplied selector - again, using a template string -
        // to create the selector:
        toHide = document.querySelectorAll(`.info-block:not(.${value})`);
    
      // using NodeList.prototype.forEach() to iterate over the
      // NodeList, passing one argument to the anonymous (Arrow)
      // function; 'el' is a reference to the current Node of
      // the NodeList we're iterating over:
      toHide.forEach(
        // and in the function we set the Node's 'hidden'
        // property-value to true (in order to hide the element):
        (el) => el.hidden = true
      );
    
      // here we set the hidden property-value of the
      // element we wish to show to false, in order
      // to show that element:
      toShow.hidden = false;
    }
    
    document.querySelectorAll('.info-block').forEach(
      (el) => el.hidden = true
    );
    document.querySelector('#productType').addEventListener('change', showOnChoice);
    label::after {
      content: ': ';
    }
    <form>
      <!-- all duplicate ids have been removed, *never* use duplicate
           ids; they're invalid and speak to either a lack of
           knowledge or lack of concern for one's code, and cause
           JavaScript problems in any situation that relies upon
           those ids: -->
      <fieldset>
        <label for="productType">Type Switcher</label>
        <select id="productType">
          <!-- you're clearly using the first <option> as the
               label/instruction for the users; this should
               never be chosen by the user so here we first
               set it as the selected option on page-load,
               and set it to disabled (a Boolean attribute
               that doesn't need a value, but if one is
               provided will always disable the element
               regardless of that value, because strings
               are truthy). This means that once the user
               opens the <select>, and navigates to another
               <option> they can't re-select this <option>
               (unless they use the developer console, but
               that's a problem for another time and another
               question): -->
          <option disabled selected>--Select a Type</option>
          <option value="DVD">DVD</option>
          <option value="Book">Book</option>
          <option value="Furniture">Furniture</option>
        </select>
      </fieldset>
    
      <div class="subform-test-class">
        <fieldset class="DVD info-block">
          <label for="DVD">Size (MB)</label>
          <input type="text" id="DVD" name="dvdSize">
          <p>*Please provide size of the DVD (MB)</p>
        </fieldset>
        <fieldset class="Book info-block">
          <label for="weight" id="book">Weight (KG)</label>
          <input type="text" id="weight" name="bookWeight">
          <p>*Please provide weight of the book in KG.</p>
        </fieldset>
    
        <fieldset class="Furniture info-block">
          <label for="height">Height</label>
          <input type="text" id="height" name="fHeight">
    
          <label for="#width">Width</label>
          <input type="text" id="width" name="fWidth">
    
          <label for="length">Length</label>
          <input type="text" id="length" name="fLength">
          <p>*Please provide size of the furniture in dimensions of HxWxL</p>
        </fieldset>
      </div>
    </form>

    Obviously, you can use jQuery if you really wish though there’s not really much reason to do so; however, if you must then the following may be of use:

    // hiding all elements matched by the selector:
    $('.info-block').hide();
    
    // binding the anonymous function of the on() method
    // as the event-handler for the 'change' event:
    $('#productType').on('change', function(){
    
      // caching the value of the <select> element
      // ('this' refers to the element to which
      // the event was triggered):
      let value = $(this).val();
      
      // here we select all elements matching the
      // supplied selector, and iterate over that
      // collection using each():
      $('.info-block').each(function(){
        // here we toggle the display of the current
        // element of the collection; to do this we
        // test to see if the element has a class-name
        // equal to the <select> element's chosen value;
        // if this evaluates to true the element is
        // shown, if it evaluates to false the
        // element is, or remains, hidden:
        $(this).toggle( $(this).hasClass(value) );
      });
    });
    label::after {
      content: ': ';
    }
    <form>
      <!-- all duplicate ids have been removed, *never* use duplicate
           ids; they're invalid and speak to either a lack of
           knowledge or lack of concern for one's code, and cause
           JavaScript problems in any situation that relies upon
           those ids: -->
      <fieldset>
        <label for="productType">Type Switcher</label>
        <select id="productType">
          <!-- you're clearly using the first <option> as the
               label/instruction for the users; this should
               never be chosen by the user so here we first
               set it as the selected option on page-load,
               and set it to disabled (a Boolean attribute
               that doesn't need a value, but if one is
               provided will always disable the element
               regardless of that value, because strings
               are truthy). This means that once the user
               opens the <select>, and navigates to another
               <option> they can't re-select this <option>
               (unless they use the developer console, but
               that's a problem for another time and another
               question): -->
          <option disabled selected>--Select a Type</option>
          <option value="DVD">DVD</option>
          <option value="Book">Book</option>
          <option value="Furniture">Furniture</option>
        </select>
      </fieldset>
    
      <div class="subform-test-class">
        <fieldset class="DVD info-block">
          <label for="DVD">Size (MB)</label>
          <input type="text" id="DVD" name="dvdSize">
          <p>*Please provide size of the DVD (MB)</p>
        </fieldset>
        <fieldset class="Book info-block">
          <label for="weight" id="book">Weight (KG)</label>
          <input type="text" id="weight" name="bookWeight">
          <p>*Please provide weight of the book in KG.</p>
        </fieldset>
    
        <fieldset class="Furniture info-block">
          <label for="height">Height</label>
          <input type="text" id="height" name="fHeight">
    
          <label for="#width">Width</label>
          <input type="text" id="width" name="fWidth">
    
          <label for="length">Length</label>
          <input type="text" id="length" name="fLength">
          <p>*Please provide size of the furniture in dimensions of HxWxL</p>
        </fieldset>
      </div>
    </form>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    In short, however, the original problem was your use of the # character within a declared id attribute-value; this is a CSS selector, but should not be present in the id itself (similarly, a . character is the selector for
    class-names, but should not be present in the class). The character can be present, but does require escaping:

    document.querySelectorAll('input').forEach(
      (el) => el.addEventListener('input', (evt) => {
        let value = evt.currentTarget.value;
    
        document.querySelector('.highlight')?.classList.remove('highlight');
          document.querySelector(
          // here we're using a template-literal (again) to interpolate the
          // value variable with the string; to select the relevant element:
          // 1. we use the '#' character,
          // 2. we then use a back-slash ('') character to escape the
          // second back-slash character, because we need to use that to
          // create a valid CSS selector in which the second '#' character
          // must be escaped with that second back-slash. This does work,
          // but complicating your development life like this does feel
          // like a ridiculous approach:
          `#\${value}`
          ).classList.add('highlight');
      })
    );
    label {
      aspect-ratio: 1.75;
      border: 2px solid lightblue;
      border-radius: 0.5rem;
      cursor: pointer;
      display: inline-flex;
      flex-direction: column;
      gap: 0.25rem;
      inline-size: 5rem;
      margin-inline-end: 0.5rem;
      padding: 0.25rem;
    }
    
    .choices {
      border: 0.25rem solid hsl(300deg 95% 65% / 0.9);
      display: flex;
      gap: 1rem;
      justify-content: center;
      padding-block: 1rem;
    }
    
    div[id] {
      aspect-ratio: 1;
      border: 0.25rem solid var(--borderColor);
      display: grid;
      flex-basis: 10%;
      place-content: center;
    }
    
    div[id]::before {
      color: #999;
      font-weight: 600;
      content: attr(id);
      padding: 0.5rem;
    }
    
    ##one {
      --borderColor: hsl(120deg 90% 95% / 1);
    }
    
    ##two {
      --borderColor: hsl(240deg 90% 95% / 1);
    }
    
    ##three {
      --borderColor: hsl(360deg 90% 95% / 1);
    }
    
    .highlight {
      background-image: repeating-linear-gradient(to bottom right, var(--borderColor) 0 5px, transparent 5px 15px);
      color: color-mix(in srgb-linear, #fff 0%, var(--borderColor));
      outline: 4px solid var(--borderColor);
      outline-offset: 0.25rem;
    }
    <h2>Choose an element to highlight:</h2>
    <!-- adding the '#' character in the value attribute-values: -->
    <label>One: <input type="radio" value="#one" name="choice"></label>
    <label>two: <input type="radio" value="#two" name="choice"></label>
    <label>three: <input type="radio" value="#three" name="choice"></label>
    
    <div class="choices">
      <!-- adding the '#' character in the id attribute-values: -->
      <div id="#one"></div>
      <div id="#two"></div>
      <div id="#three"></div>
    </div>

    References:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search