jquery 如何防止在Laravel 8应用中默认提交通过Ajax加载的表单?

tpgth1q7  于 2024-01-07  发布在  jQuery
关注(0)|答案(4)|浏览(152)

我在Laravel 8中做了一个blogging application。我目前正在通过jQuery(v3.5.0)AJAX添加 * 评论回复 *。
comment-form.blade.php中,我有:

  1. <div class="form-wrapper">
  2. <div class="alert-box-ajax alert-box alert-box--success">
  3. Your comment is pending
  4. </div>
  5. <div class="alert-box-ajax alert-box alert-box--error">
  6. Failed to add comment!
  7. </div>
  8. <form class="commentForm" method="post" action="{{ route('comment.submit') }}" autocomplete="off" novalidate>
  9. @csrf
  10. <fieldset>
  11. <input type="hidden" name="article_id" value="{{ isset($article->id) ? $article->id : $article_id }}">
  12. <input type="hidden" name="parent_id" value="{{ $comment->id ?? '' }}">
  13. <div class="message form-field">
  14. <textarea name="msg" id="message" class="h-full-width" placeholder="Your Message" required></textarea>
  15. @error('msg')
  16. <p class="help-block text-danger">{{ $message }}</p>
  17. @enderror
  18. </div>
  19. <br>
  20. <input name="submit" id="submit" class="btn btn--primary btn-wide btn--large h-full-width" value="Add Comment" type="submit">
  21. </fieldset>
  22. </form>
  23. </div>

字符串
当然,上面的模板对每个评论都重复,这样回复就可以添加到任何评论中。
回复通过jQuery Ajax提交:

  1. $(".commentForm").each(function () {
  2. var form = $(this);
  3. form.validate({
  4. errorElement: "p",
  5. errorClass: "help-block text-danger",
  6. submitHandler: function (_form, event) {
  7. event.preventDefault();
  8. var $fields = form.find("textarea"),
  9. url = form.attr("action"),
  10. data = form.serialize();
  11. $.ajax({
  12. dataType: "json",
  13. type: "post",
  14. url: url,
  15. data: data,
  16. cache: false,
  17. success: function (response) {
  18. if (response.status === 'success') {
  19. form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250)
  20. .slideDown(250)
  21. .delay(2500)
  22. .slideUp(250);
  23. $fields.val("");
  24. } else {
  25. form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250)
  26. .slideDown(250)
  27. .delay(2500)
  28. .slideUp(250);
  29. }
  30. },
  31. error: function (err) {
  32. console.log(err);
  33. },
  34. });
  35. },
  36. });
  37. });


问题
有一个选项可以为每个帖子初始加载最多10个comemnts,其余的通过Ajax调用加载到页面滚动中。
当此选项处于活动状态时,上面的脚本无法阻止通过Ajax加载的表单的默认行为。

**!注意:**问题不是提交事件,而是提交事件的 * 预防 *。

常见问题

1.是什么导致了这个问题?
1.解决这个问题最可靠的方法是什么?

q7solyqu

q7solyqu1#

这将工作,无论有多少形式为每个评论,因为每个形式将属于单一的评论。

  1. $(document).on("submit", ".commentForm", function (event) {
  2. event.preventDefault();
  3. var form = $(this);
  4. form.validate({
  5. errorElement: "p",
  6. errorClass: "help-block text-danger",
  7. submitHandler: function (_form, event) {
  8. event.preventDefault();
  9. var $fields = form.find("textarea"),
  10. url = form.attr("action"),
  11. data = form.serialize();
  12. $.ajax({
  13. dataType: "json",
  14. type: "post",
  15. url: url,
  16. data: data,
  17. cache: false,
  18. success: function (response) {
  19. if (response.status === 'success') {
  20. form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250)
  21. .slideDown(250)
  22. .delay(2500)
  23. .slideUp(250);
  24. $fields.val("");
  25. } else {
  26. form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250)
  27. .slideDown(250)
  28. .delay(2500)
  29. .slideUp(250);
  30. }
  31. },
  32. error: function (err) {
  33. console.log(err);
  34. },
  35. });
  36. },
  37. });
  38. });

字符串

展开查看全部
pu82cl6c

pu82cl6c2#

您遇到的问题是由于jQuery .each()函数和.validate()方法只应用于代码运行时存在于DOM中的元素。这意味着稍后(通过AJAX)添加到DOM的任何元素(在您的情况下,注解表单)都不会应用这些方法。
要解决这个问题,您可以使用事件委托。事件委托允许您将单个事件侦听器附加到父元素,该侦听器将为匹配选择器的所有后代触发,无论这些后代现在存在还是将来添加。
以下是如何修改jQuery代码以使用事件委托:

  1. $(document).on('submit', '.commentForm', function(event) {
  2. event.preventDefault();
  3. var form = $(this);
  4. var $fields = form.find("textarea"),
  5. url = form.attr("action"),
  6. data = form.serialize();
  7. $.ajax({
  8. dataType: "json",
  9. type: "post",
  10. url: url,
  11. data: data,
  12. cache: false,
  13. success: function (response) {
  14. if (response.status === 'success') {
  15. form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250)
  16. .slideDown(250)
  17. .delay(2500)
  18. .slideUp(250);
  19. $fields.val("");
  20. } else {
  21. form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250)
  22. .slideDown(250)
  23. .delay(2500)
  24. .slideUp(250);
  25. }
  26. },
  27. error: function (err) {
  28. console.log(err);
  29. },
  30. });
  31. });

字符串
我是这么想的。新代码:

  1. $(document).on('submit', '.commentForm', function (event) {
  2. event.preventDefault();
  3. var form = $(this);
  4. form.validate({
  5. errorElement: "p",
  6. errorClass: "help-block text-danger",
  7. rules: {
  8. msg: "required",
  9. },
  10. messages: {
  11. msg: "Enter a comment",
  12. }
  13. });
  14. // Check if the form is valid
  15. if (!form.valid()) {
  16. return;
  17. }
  18. var $fields = form.find("textarea"),
  19. url = form.attr("action"),
  20. data = form.serialize();
  21. $.ajax({
  22. dataType: "json",
  23. type: "post",
  24. url: url,
  25. data: data,
  26. cache: false,
  27. success: function (response) {
  28. if (response.status === 'success') {
  29. form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250)
  30. .slideDown(250)
  31. .delay(2500)
  32. .slideUp(250);
  33. $fields.val("");
  34. } else {
  35. form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250)
  36. .slideDown(250)
  37. .delay(2500)
  38. .slideUp(250);
  39. }
  40. },
  41. error: function (err) {
  42. console.log(err);
  43. },
  44. });
  45. });

展开查看全部
91zkwejq

91zkwejq3#

这个问题已经在评论中解释过了。你所展示的JavaScript在页面加载时运行,那里的选择器只会匹配页面加载时存在的元素。如果你稍后动态添加元素,Javascript不会再次运行,那些选择器不会匹配它们。
在这种情况下,这意味着$(".commentForm")只匹配那些在页面加载时存在的具有该类的表单,因此只有这些表单才会应用验证代码。当您稍后向页面添加新的$(".commentForm") s时,在页面加载时运行的JS不会再次为新表单运行,并且它们根本没有验证。提交这些表单不会运行任何JavaScript,它们只是正常提交,这就是你所看到的
为了解决这个问题,你可以让你的验证成为一个可以随时调用的函数,例如:

  1. // Function to initialise validation on the passed form element.
  2. // $form is a jQuery object. Note you now need to use $form to
  3. // reference the form being validated, eg $form.find("textarea"),
  4. // $form.closest(), etc, inside the function.
  5. function commentFormValidation($form) {
  6. $form.validate({
  7. // ... your validation code.
  8. submitHandler: function (_form, event) {
  9. event.preventDefault();
  10. let $fields = $form.find("textarea");
  11. $.ajax({
  12. // ...
  13. });
  14. },
  15. });
  16. }
  17. // At page load, apply validation to each form that exists at that time
  18. $(".commentForm").each(function () {
  19. commentFormValidation($(this));
  20. });

字符串
现在你可以在一个新表单被添加到DOM的时候动态地添加验证。你还没有给我们展示添加新表单的代码,但是为了演示的目的,假设你正在克隆一些主表单模板,可能是这样的:

  1. // Pseudo/simplified code, this is just for demonstration
  2. let $template = $('#commentForm-template'); // some master template
  3. let $copy = $template.clone(); // create a copy
  4. $copy.appendTo('.someContainer'); // add it to DOM somewhere
  5. commentFormValidation($copy); // add validation to it


无论代码是什么样子,你需要做的唯一重要的部分就是在新表单上调用新的验证函数:

  1. commentFormValidation($newFormJQueryObject);


类似问题供参考:

或者,您也可以使用事件委托来实现这一点,尽管这有点棘手,而且IMO并不是一个整洁的解决方案。
首先,我们需要将事件处理程序附加到页面加载时存在的选择器,并且将成为当前和未来所有表单的父级。让我们称之为.someContainer。接下来我们过滤选择器以仅匹配表单:

  1. $('.someContainer').on('submit', '.commentForm', function(e) {
  2. e.preventDefault();
  3. // ...


现在,在该容器内发生的任何submit事件都会触发此处理程序-即使是页面加载后添加的表单。无需添加单独的代码来处理页面加载时存在的表单,这将捕获所有表单。
接下来,我们显然需要添加代码来初始化刚刚提交的表单上的验证。我们可以使用现有的commentFormValidation()函数来完成这一点:

  1. $('.someContainer').on('submit', '.commentForm', function(e) {
  2. e.preventDefault();
  3. commentFormValidation($(this));
  4. // ...


但是有一个问题。提交表单会添加验证,但它实际上不会 * 运行 * 验证。因此,第一次提交表单时,什么都不会发生,因为提交操作已被此处理程序拦截,添加了验证,.
所以我们需要在添加验证后手动运行它,你可以通过在表单上调用the .valid() method来完成--尽管它在这里不起作用,我不知道为什么。
因此,我们可以手动重新提交表单,这将运行验证。
这里有一个演示这种委托方法的工作片段。检查控制台输出以查看发生的各个阶段。

  1. function commentFormValidation($form) {
  2. $form.validate({
  3. rules: {
  4. foo: 'required'
  5. },
  6. submitHandler: function (_form, event) {
  7. event.preventDefault();
  8. console.log('submitHandler running');
  9. },
  10. });
  11. }
  12. $('.someContainer').on('submit', '.commentForm', function(e) {
  13. e.preventDefault();
  14. console.log('event handler running');
  15. // Initialise validation on this form
  16. commentFormValidation($(this));
  17. // Manually run the validation on this form - not sure why, does
  18. // not work
  19. // $(this).valid();
  20. // Manually re-submit the form to trigger validation
  21. $(this).submit();
  22. });
  1. <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  2. <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.validate.min.js"></script>
  3. <div class="someContainer">
  4. <form class="commentForm">
  5. <input type="text" name="foo">
  6. <button>Submit</button>
  7. </form>
  8. </div>

的字符串

展开查看全部
nfzehxib

nfzehxib4#

一个简单的解决方法是区分初始化和未初始化的内容。让我们创建一个函数,将其 Package 在代码中,并确保稍微修改代码以初始化未初始化的元素:

  1. function initializeForms() {
  2. $(".commentForm:not(.initialized)").each(function () {
  3. var form = $(this);
  4. form.addClass("initialized"); //We initialized your form, so we mark it as such
  5. form.validate({
  6. errorElement: "p",
  7. errorClass: "help-block text-danger",
  8. submitHandler: function (_form, event) {
  9. event.preventDefault();
  10. var $fields = form.find("textarea"),
  11. url = form.attr("action"),
  12. data = form.serialize();
  13. $.ajax({
  14. dataType: "json",
  15. type: "post",
  16. url: url,
  17. data: data,
  18. cache: false,
  19. success: function (response) {
  20. if (response.status === 'success') {
  21. form.closest(".form-wrapper").find(".alert-box--success").slideDown(250).delay(2500).slideUp(250)
  22. .slideDown(250)
  23. .delay(2500)
  24. .slideUp(250);
  25. $fields.val("");
  26. } else {
  27. form.closest(".form-wrapper").find(".alert-box--error").slideDown(250).delay(2500).slideUp(250)
  28. .slideDown(250)
  29. .delay(2500)
  30. .slideUp(250);
  31. }
  32. },
  33. error: function (err) {
  34. console.log(err);
  35. },
  36. });
  37. },
  38. });
  39. });
  40. }

字符串
请确保在页面加载时以及“下一个内容”AJAX完成并追加新表单时调用此函数。
编辑
你还需要小心,因为如果容器的innerHTML被改变,那么所有的事件监听器都会被破坏。所以你需要测试当你加载下一个10个元素时,你的第一个元素是否仍然工作。如果是这样,那么我的初始解决方案就可以工作。如果不是,那么你可以将初始行改为$(".commentForm:not(.initialized)").each(function () {并删除form.addClass("initialized");行。
编辑2
下面是一个创建事件并在容器的.innerHTML`更改后重新创建事件的工作示例:

  1. function customSubmit(evt) {
  2. evt.preventDefault();
  3. evt.currentTarget.querySelector("input").value = "clicked me";
  4. }
  5. function customGroupSubmit(container) {
  6. for (let form of container.querySelectorAll("form")) {
  7. form.addEventListener("submit", customSubmit);
  8. }
  9. }
  10. let container = document.querySelector(".container");
  11. customGroupSubmit(container);
  12. document.getElementById("add").addEventListener("click", function() {
  13. let template = `<div class="commentForm"><form><input type="submit" value="click me"></form></div>`;
  14. template = template + template + template;
  15. container.innerHTML += template;
  16. customGroupSubmit(container);
  17. });
  1. <div class="container">
  2. <div class="commentForm"><form><input type="submit" value="click me"></form></div>
  3. <div class="commentForm"><form><input type="submit" value="click me"></form></div>
  4. <div class="commentForm"><form><input type="submit" value="click me"></form></div>
  5. </div>
  6. <input type="button" id="add" value="add">

的数据

展开查看全部

相关问题