用值填充 123FormBuilder 字段

Populate 123FormBuilder Field with value

提问人:Twisty 提问时间:11/4/2023 最后编辑:Twisty 更新时间:11/14/2023 访问量:72

问:

这个问题可能对 123FormBuilder 来说太具体了,但我把它放在那里是希望有人能有所了解。

我正在将自定义 HTML 与 jQuery 一起添加到表单中,以允许用户从可用停车位的图像中选择 1 个停车位(例如在剧院中选择座位)。包含以下代码。

var $drop = $("[data-id='109672317'] select");
var $rvSpot = $("[data-id='110061531'] input");

$("path.enabled").on("mouseover", function(){
  $(this).toggleClass("highlight");
}).on("mouseout", function(){
  $(this).toggleClass("highlight")
}).on("click", makeSelection);

function makeSelection(e){
  var el = $(e.target);
  var l = $drop.find("option:selected").data("index");
  var s = el.attr("id");
  console.log("Making Selection", l, s);
  if($(".selected").length){
    if(!confirm("Are you sure you want to change your Parking Selection?")){
      return false;
    }
    removeSelected(l, e.target);
  }
  $.post("https://myurl.tld/take-spot.php", { land: l, spot: s }, function(results){
    el.addClass("selected");
    $rvSpot.trigger("focus").val(s).trigger("blur");
    console.log($rvSpot.val());
    startCountdown();
  });
}

function removeSelection(l, el){
  s = $(el).attr('id');
  console.log("Removing Selection", l, s)
  $.post("https://myurl.tld/release-spot.php", { land: l, spot: s }, function(){
    $(".selected").removeClass("selected");
    $rvSpot.trigger("focus").val(0).trigger("blur");
    stopCountdown();
  });
}

function startCountdown(){
  var m = 09, s = 60, t, $ct = $(".countdown .timeleft");
  $ct.html("10:00");
  $ct.data("timer", setInterval(function(){
    s--;
    if(s == 00){
      m--;
      s = 59;
    }
    if(m < 2){
      $ct.css("color", "red");
    }
    if(m == 00 && s == 00){
      stopCountdown();
      removeSelection($(".image-map", $(".selected")));
    }
    $ct.html(m + ":" + s);
  }, 1000));
}

function stopCountdown(){
  clearInterval($(".countdown .timeleft").data("timer"));
}

这里有一些文档,建议您必须设置控件与输入字段的值。下面是一个 HTML 片段:

<div data-role="container" data-type="virtual-form-table-row" data-hash="0000001d" data-type-id="0" data-colspan="20" data-num-children="1">
  <div data-role="control" data-type="text" data-hash="0000001c" data-type-id="23" data-colspan="20" data-is-hidden="1" data-renderer-type="tln" data-id="110061531"><label data-role="label" id="text-0000001c-acc" data-i18n-text="control_label_110061531">Parking Spot</label><dt data-role="instructions" id="text-0000001c-instr-acc" data-is-empty="1" data-i18n-text="control_instructions_110061531"></dt>
    <div data-role="input-row" data-is-first-row="1" data-is-last-row="1" data-fill-colspan="0">
      <div data-role="input-container" data-ui-role="ui-element" data-size="full"><span data-role="prefix-label" id="price-0000001c-prefix-acc" style="display: none;"></span><input type="text" data-role="i123-input" data-no-theme="" aria-labelledby="text-0000001c-acc text-0000001c-error-acc text-0000001c-instr-acc" id="text-0000001c"
          value="0" placeholder="" style="padding-left: 8px;"></div>
    </div><label data-role="error" id="text-0000001c-error-acc" data-is-empty="1"></label></div>
</div>

我可以看到 Control 元素,但不清楚如何更新它,以便表单在提交时接受此数据。

更新

我让它工作过一次,但一直无法复制它。

我更新了代码如下:

$rvSpot.trigger("focus").attr("value", s).trigger("blur");

当我检查元素时,它似乎确实发生了属性更改,但是当我提交表单并查看结果时,我仍然有一个值。input0

jQuery 表单

评论

0赞 Mark Schultheiss 11/8/2023
也许只是先更改以填充值,然后触发触发器,即$rvSpot.trigger("focus").attr("value", s).trigger("blur");$rvSpot.val(s).trigger("focus").trigger("blur");
0赞 Mark Schultheiss 11/8/2023
请注意,代码还有其他挑战/改进,但可能不是手头问题的一部分。
0赞 Twisty 11/8/2023
@MarkSchultheiss我会试一试。主要问题是在提交表单时,没有遇到值。正如所建议的,也许有一些我不知道的验证脚本。

答:

1赞 VonC 11/7/2023 #1

在不了解 123FormBuilder 的情况下,我觉得很奇怪:我会使用 .val(s),这是在 jQuery 中设置输入元素值的正确方法(例如,参见“jQuery 中 attr() 和 val() 之间的区别”)。.attr("value", s)

仔细检查选择器是否正确,并且是否针对正确的元素。并确保 value 属性直接位于输入元素上,并且没有其他脚本或表单验证可能会在提交时将值重置为。$rvSpot0

我还会使用 .on( “change” [, eventData ], handler)(因为 .change(处理程序 API 已弃用在设置值后触发更改事件。这很重要,因为某些窗体会侦听 change 事件以注册值已更新。

+------------------+           +-----------------+
| User Interaction | --click-> | makeSelection() |
+------------------+           +-----------------+
         |                                     |
         |                                     |
         v                                     v
+------------------+           +------------------+
| Update $rvSpot   |           | startCountdown() |
+------------------+           +------------------+

更新后的代码为:

// rest of your code

function makeSelection(e){
  // existing code
  $.post("https://myurl.tld/take-spot.php", { land: l, spot: s }, function(results){
    el.addClass("selected");
    $rvSpot.val(s).trigger("change"); // use trigger to programmatically trigger the change event
    console.log($rvSpot.val()); // for debugging
    startCountdown();
  });
}

// rest of your code

// Bind change event handler to $rvSpot if needed elsewhere in the code
$rvSpot.on("change", function() {
  // Handler code here
});

这应该正确更新 的值,并通知任何其他事件侦听器该值已更改。$rvSpot

请记住验证输入元素的名称和 ID 属性,以确保表单在提交表单时能够识别输入。


另一种方法将在如何预填充表单字段中介绍:123FormBuilder 支持预填充表单字段,方法是使用与表单字段 ID 和要预填充的值相对应的参数构造自定义 URL。当您希望根据已知信息将用户定向到已填写某些字段的表单时,这很有用。

但是,此方法与您一直使用的方法不同,后者涉及在表单已加载到用户浏览器中后使用 JavaScript 动态设置表单字段的值。

根据 123FormBuilder 文档,表单字段不是通过使用 jQuery 操作 DOM 元素来直接填充的(就像您尝试使用 时所做的那样)。相反,您将使用表单的字段 ID 和所需的预填充值作为查询参数来构造 URL。$rvSpot.val(s).trigger("change")

对于 JavaScript 代码中描述的方案,您似乎希望在用户与表单交互时实时更新表单字段,而不是在表单加载之前通过 URL 预填充表单字段。因此,123FormBuilder 文档中的预填充 URL 方法不直接适用于您的情况。


在 JavaScript 代码中,当您动态设置输入的值并希望表单在提交时识别此值时,您需要确保:

  1. JavaScript 代码正确更新输入字段的值。
  2. 表单生成器用于检测更改的任何事件侦听器都会被触发。
  3. 表单的提交过程可识别动态设置的值。

如果表单提交无法识别 JavaScript 更新的值,则可能是由于表单生成器跟踪更改或验证输入的内部机制所致,这可能预示着 JavaScript 方法未复制的用户输入事件。.trigger("change")

上面提到的处理程序 () 与第 2 点有关。
一个例子是
$rvSpot.on("change", function() {...}

$rvSpot.on("change", function() {
  // That is the handler code that will run every time the value of $rvSpot changes.
  var newValue = $(this).val();
  
  // You might want to perform some validation, logging, or other functionality when the value changes.
  console.log("New parking spot selected:", newValue);

  // If the form relies on some validation or additional processing on change events,
  // you would include that logic here. For example:
  validateParkingSpot(newValue); // A hypothetical function to validate the selection.
  
  // Or, if you need to enable/disable a submit button based on this value:
  var isFormValid = newValue !== "0" && newValue !== ""; // Simple validation check.
  $("#submit-button").prop("disabled", !isFormValid); // Enable/disable the button.
});

这就是确保表单的提交过程识别动态设置值的方式,因为处理程序确保在输入值更改时处理从验证到启用提交按钮的所有步骤,无论该更改是直接来自用户还是来自脚本。


.attr("value")不是一个好方法,但我尝试了,没有得到改进的结果;所以我在尝试替代。.val()

检查元素,它具有从 123Forms 绑定到它的事件。我没有看到任何变化。Inputfocusblurfor

我怀疑你是对的,我需要找到一些更高的形式验证。似乎仅仅将值添加到中并不足以让它被接受。Input

如果输入元素绑定了 和 事件,则 123FormBuilder 可能会将这些事件用作其验证或状态管理系统的一部分。缺少直接更改事件处理程序并不一定意味着不会检测到对输入值的更改,但它确实表明表单可能依赖于 和 事件来触发其内部更改检测机制。focusblurfocusblur

将值设置为 后,可以尝试触发 和 事件来模拟用户交互:.val()focusblur

$rvSpot.val(s).trigger("focus").trigger("blur");

这与Mark Schultheiss的评论类似:

也许只是先更改以填充值,然后触发触发器,即$rvSpot.trigger("focus").attr("value", s).trigger("blur");$rvSpot.val(s).trigger("focus").trigger("blur");

这应该模仿用户选择一个值:输入获取值,用户“关注”输入(),然后远离它()。如果表单生成器正在寻找这些事件来验证或处理输入,则此序列更有可能被识别为合法的用户操作。(val(s))trigger("focus")trigger("blur")

表单可能将其他事件处理程序附加到其字段,以便进行验证或其他目的。您可以在浏览器的开发人员工具中检查该元素,以查看是否存在代码中未立即可见的事件侦听器。

如果表单生成器使用更复杂的机制来跟踪更改,则可能需要使用 MutationObserver 来监视对输入元素的更改并做出相应的反应。

确保输入字段具有与服务器预期内容相对应的属性。表单数据在提交时通常由属性键控。namename

如果所有其他方法都失败,并且您可以控制服务器端逻辑,请考虑在提交表单后直接在服务器上更新值。这将是一个不太优雅的解决方案,只有在没有其他选项工作时才应该使用。

评论

0赞 Twisty 11/8/2023
都是优点。正如你指出的,这不是一个好方法,但我尝试过,没有得到改进的结果;所以我在尝试替代。检查 Input 元素,它具有从 123Forms 绑定到它的事件。我没有看到任何.我怀疑你是对的,我需要找到一些更高的形式验证。似乎仅仅向 Input 添加值不足以让它被接受。.attr("value").val()focusblurchange
0赞 VonC 11/8/2023
@Twisty我已经编辑了答案以解决您的评论。
0赞 Twisty 11/8/2023
如果有帮助,这里是表格: form.123formbuilder.com/6529883/2024-test-theater 试图避免操作呈现的元素(例如添加/删除名称属性)。今晚晚些时候我会尝试您的建议。
0赞 Twisty 11/8/2023
到目前为止,没有任何变体起作用。检查表单本身的验证功能。
1赞 VonC 11/9/2023
@Twisty 假设表单具有自定义事件处理程序和自定义事件,听起来表单的逻辑被封装在JavaScript类中,并且它侦听特定的自定义事件以处理值更改。如果您有权访问表单的 JavaScript,则可以直接触发自定义事件。但是,如果事件处理程序是封闭作用域或类的一部分,则如果不引用类的实例,则可能无法从该作用域外部触发它。onControlValueChangedBecauseOfUserInputvalue-change
1赞 Twisty 11/14/2023 #2

我终于在这里找到了答案:

https://www.123formbuilder.com/docs/js-tips-how-to-pass-an-input-from-one-field-to-another-in-the-same-form/

似乎有一个带有 Get 和 Set 方法的处理程序。

这是工作代码。

var $drop = $("[data-id='000000000']");
var $rvSpot = $("[data-id='000000000']");
var targetControlId = 000000000,
targetControlInstance = loader.getEngine().getDocument().getElementById(targetControlId);

$("path.enabled").on("mouseover", function(){
  $(this).toggleClass("highlight");
}).on("mouseout", function(){
  $(this).toggleClass("highlight")
}).on("click", makeSelection);

function makeSelection(e){
  var el = $(e.target);
  var l = $drop.find("select option:selected").data("index");
  var s = el.attr("id");
  if($(".selected").length){
    if(!confirm("Are you sure you want to change your RV Selection?")){
      return false;
    }
    removeSelected(l, el, function(){
      console.log("Spot removed, callback executed");
      makeSelection(e);
    });
  } else {
      console.log("Making Selection", l, s);
      $.post("https://www.unscruz.org/ticketing/take-spot.php", { land: l, spot: s }, function(results){
          el.addClass("selected");
          targetControlInstance.setValue({value: s});
          $(".countdown").append("<span id='spot-selected'>Selected: " + s + "</span>");
          startCountdown();
      });
  }
}

function removeSelected(l, el, callback){
    var s = $(el).attr('id');
    console.log("Removing Selection", l, s);
    $.post("https://www.unscruz.org/ticketing/release-spot.php", { land: l, spot: s }, function(){
        $(".selected").removeClass("selected");
        targetControlInstance.setValue({value: ""});
        stopCountdown();
        if(callback != undefined && typeof callback == "function"){
            callback();
        }
    });
}

评论

0赞 VonC 11/14/2023
抓得好,干得好。点赞。