Dynamic div label/id in UI page

ray evans
Tera Guru

I'm struggling to get my dynamic div and labels to update with the value of count - 

<j:jelly xmlns:j="jelly:core" xmlns:g="glide">
    <j:set var="sys_id" value="${RP.getParameterValue('sysparm_sys_id')}" />
    <j:set var="jvar_quantity" value="${RP.getParameterValue('sysparm_quantity')}" />
    <j:set var="price" value="${RP.getParameterValue('sysparm_price')}" />

    <html>
    <head>
        <title>Dynamic Divs Example</title>
        <style>
            .dynamicDiv {
                display: flex;
                flex-direction: column;
                gap: 10px;
                margin-bottom: 20px;
                border: 1px solid #ccc;
                padding: 10px;
                border-radius: 5px;
            }
            .dynamicDiv h3 {
                margin: 0 0 10px 0;
            }
            .form-group {
                display: flex;
                align-items: center;
                gap: 10px;
            }
            .form-group label {
                width: 150px;
            }
            .form-group g\\:ui_reference {
                flex: 1;
            }
        </style>
    </head>
    <body>
        <div id="divContainer">
            <script>
                var count = 0;
            </script>
            <j:forEach var="i" begin="1" end="${jvar_quantity}">
                <script>
                    count++;
                </script>
                <div id="div_${count}" class="dynamicDiv">
                    <h3>Label ${count}</h3>
                    <div class="form-group">
                        <label for="user_${count}">User ${count}:</label>
                        <g:ui_reference class="form-control" id="user_${count}" name="user_${count}" required="true" table="sys_user" query="company=71f448c71b720510349f40c4e34bcbd3&amp;active=true" />
                    </div>
                    <div class="form-group">
                        <label for="assetTag_${count}">Asset Tag ${count}:</label>
                        <g:ui_reference class="form-control" id="assetTag_${count}" name="assetTag_${count}" table="cmdb_ci_hardware" required="true" query="company=71f448c71b720510349f40c4e34bcbd3&amp;asset_tagSTARTSWITHNHSG&amp;asset_tagNOT%20LIKENHSG-&amp;sys_class_name=cmdb_ci_computer&amp;ORsys_class_name=u_cmdb_ci_laptop_computer&amp;ORsys_class_name=u_cmdb_ci_desktop_computer&amp;ORsys_class_name=u_cmdb_ci_tablet_computer" />
                    </div>
                </div>
                <script>
                    console.log("Current count: " + count);
                </script>
            </j:forEach>
        </div>

        <script>
            document.addEventListener("DOMContentLoaded", function() {
                const dynamicDivs = document.querySelectorAll('.dynamicDiv');
                dynamicDivs.forEach((div, index) => {
                    console.log(`Index: ${index}`);
                    const titleLabel = document.createElement('label');
                    titleLabel.textContent = `Title for Div ${index + 1}`;
                    div.insertBefore(titleLabel, div.firstChild);
                });
            });
        </script>

        <script>
            console.log('Parameters in Jelly script:', 'sys_id:', '${sys_id}', 'quantity:', '${jvar_quantity}', 'price:', '${price}');
        </script>
    </body>
    </html>
</j:jelly>
1 ACCEPTED SOLUTION

ray evans
Tera Guru

I managed to achieve this using the code below. This now creates divs and reference fields, using the dynamic div_id as a prefix for the field ID, based on a quantity value:

<j:jelly xmlns:j="jelly:core" xmlns:g="glide">
  <j:set var="jvar_quantity" value="${RP.getParameterValue('sysparm_quantity')}" />

  <html>
    <head>
      <title>Dynamic Divs Example</title>
      <style>
        .dynamicDiv {
          display: flex;
          flex-direction: column;
          gap: 10px;
          margin-bottom: 20px;
          border: 1px solid #ccc;
          padding: 10px;
          border-radius: 5px;
        }
        .dynamicDiv h3 {
          margin: 0 0 10px 0;
        }
        .form-group {
          display: flex;
          align-items: center;
          gap: 10px;
        }
        .form-group label {
          width: 150px;
        }
        .form-group g\\:ui_reference {
          flex: 1;
        }
      </style>
    </head>
    <body>
      <div id="divContainer">
        <script>
          var count = 0;
        </script>

        <j:forEach var="i" begin="1" end="${jvar_quantity}">
          <!-- Hidden block with fields -->
          <div id="block_${i}" style="display: none;">
            <div class="form-group">
              <label for="user_${i}">User ${i}:</label>
              <g:ui_reference name="user_${i}" id="user_${i}" table="sys_user"
                query="company=71f448c71b720510349f40c4e34bcbd3^active=true"
                required="true" class="form-control" />
            </div>

            <div class="form-group">
              <label for="assetTag_${i}">Asset Tag ${i}:</label>
              <g:ui_reference name="assetTag_${i}" id="assetTag_${i}" table="cmdb_ci_hardware"
                query="company=71f448c71b720510349f40c4e34bcbd3^asset_tagSTARTSWITHNHSG^asset_tagNOT LIKENHSG-^sys_class_name=cmdb_ci_computer^ORsys_class_name=u_cmdb_ci_laptop_computer^ORsys_class_name=u_cmdb_ci_desktop_computer^ORsys_class_name=u_cmdb_ci_tablet_computer"
                required="true" class="form-control" />
            </div>
          </div>

          <!-- JavaScript to create and populate the dynamic div -->
          <script>
            count++;
            var divId = 'div_' + count;

            // Create the main div
            var div = document.createElement('div');
            div.id = divId;
            div.className = 'dynamicDiv';
            document.getElementById('divContainer').appendChild(div);

            // Add a heading
            var label = document.createElement('h3');
            label.innerHTML = 'User ' + count;
            div.appendChild(label);

            // Move and update the fields
            var fields = document.getElementById('block_${i}');
            if (fields) {
              fields.style.display = 'block';

              // Update IDs and labels
              var inputs = fields.querySelectorAll('[id]');
              inputs.forEach(function(input) {
                var oldId = input.id;
                var newId = divId + '_' + oldId;
                input.id = newId;
                input.name = newId;

                var label = fields.querySelector('label[for="' + oldId + '"]');
                if (label) {
                  label.setAttribute('for', newId);
                }
              });

              div.appendChild(fields);
            }
          </script>
        </j:forEach>
      </div>
    </body>
  </html>
</j:jelly>

View solution in original post

1 REPLY 1

ray evans
Tera Guru

I managed to achieve this using the code below. This now creates divs and reference fields, using the dynamic div_id as a prefix for the field ID, based on a quantity value:

<j:jelly xmlns:j="jelly:core" xmlns:g="glide">
  <j:set var="jvar_quantity" value="${RP.getParameterValue('sysparm_quantity')}" />

  <html>
    <head>
      <title>Dynamic Divs Example</title>
      <style>
        .dynamicDiv {
          display: flex;
          flex-direction: column;
          gap: 10px;
          margin-bottom: 20px;
          border: 1px solid #ccc;
          padding: 10px;
          border-radius: 5px;
        }
        .dynamicDiv h3 {
          margin: 0 0 10px 0;
        }
        .form-group {
          display: flex;
          align-items: center;
          gap: 10px;
        }
        .form-group label {
          width: 150px;
        }
        .form-group g\\:ui_reference {
          flex: 1;
        }
      </style>
    </head>
    <body>
      <div id="divContainer">
        <script>
          var count = 0;
        </script>

        <j:forEach var="i" begin="1" end="${jvar_quantity}">
          <!-- Hidden block with fields -->
          <div id="block_${i}" style="display: none;">
            <div class="form-group">
              <label for="user_${i}">User ${i}:</label>
              <g:ui_reference name="user_${i}" id="user_${i}" table="sys_user"
                query="company=71f448c71b720510349f40c4e34bcbd3^active=true"
                required="true" class="form-control" />
            </div>

            <div class="form-group">
              <label for="assetTag_${i}">Asset Tag ${i}:</label>
              <g:ui_reference name="assetTag_${i}" id="assetTag_${i}" table="cmdb_ci_hardware"
                query="company=71f448c71b720510349f40c4e34bcbd3^asset_tagSTARTSWITHNHSG^asset_tagNOT LIKENHSG-^sys_class_name=cmdb_ci_computer^ORsys_class_name=u_cmdb_ci_laptop_computer^ORsys_class_name=u_cmdb_ci_desktop_computer^ORsys_class_name=u_cmdb_ci_tablet_computer"
                required="true" class="form-control" />
            </div>
          </div>

          <!-- JavaScript to create and populate the dynamic div -->
          <script>
            count++;
            var divId = 'div_' + count;

            // Create the main div
            var div = document.createElement('div');
            div.id = divId;
            div.className = 'dynamicDiv';
            document.getElementById('divContainer').appendChild(div);

            // Add a heading
            var label = document.createElement('h3');
            label.innerHTML = 'User ' + count;
            div.appendChild(label);

            // Move and update the fields
            var fields = document.getElementById('block_${i}');
            if (fields) {
              fields.style.display = 'block';

              // Update IDs and labels
              var inputs = fields.querySelectorAll('[id]');
              inputs.forEach(function(input) {
                var oldId = input.id;
                var newId = divId + '_' + oldId;
                input.id = newId;
                input.name = newId;

                var label = fields.querySelector('label[for="' + oldId + '"]');
                if (label) {
                  label.setAttribute('for', newId);
                }
              });

              div.appendChild(fields);
            }
          </script>
        </j:forEach>
      </div>
    </body>
  </html>
</j:jelly>