【问题标题】:Javascript is Loading Page Too Soon - Django Edit FormJavascript 加载页面太快了 - Django 编辑表单
【发布时间】:2021-10-19 21:05:54
【问题描述】:

我正在尝试编辑我网站上的现有帖子(表单),但是当我单击“编辑”时,我在控制台中得到了这个:Fetch finished loading: POST "http://127.0.0.1:8000/edit_post/ 18"。 状态为 201,所以我认为该页面跳过了大部分 javascript 并直接将其发布/保存到服务器。此外,当我单击“编辑”时,应该立即出现一个文本框,其中包含我的帖子文本。但这永远不会打开,它只是说 fetch 在控制台中适当地完成加载。

如何确保首先运行所有 Javascript?我尝试使用 preventDefault 并继续遇到未捕获的类型错误。我对 Javascript 还很陌生,所以我还在学习这个。

例如,我在 event_handeler 函数中尝试的一件事是:

document.querySelectorAll("#textarea").addEventListener("submit", function(event) {
document.querySelector(`#post-edit-${id}`).innerHTML += "Sorry!";
event.preventDefault();
})

但我遇到了未捕获的类型错误。

function edit_handeler(element) {
  id = element.getAttribute("data-id");

  document.querySelector(`#post-edit-${id}`).style.display = "block";
  document.querySelector(`#post-content-${id}`).style.display = "none";

edit_btn = document.querySelector(`#edit-btn-${id}`);
edit_btn.textContent = "Save";
edit_btn.setAttribute("class", "text-success edit");
if (edit_btn.textContent == "Save") {
edit_post(id, document.querySelector(`#post-edit-${id}`).value); //here

edit_btn.textContent = "Edit";
edit_btn.setAttribute("class", "text-primary edit");
}}


function edit_post(id, post) {
 const body = document.querySelector(`#post-content-${id}`).value; 

fetch(`/edit_post/${id}`, {

method: "POST",
body: JSON.stringify({
body:body
})


 }).then((res) => {
 document.querySelector(`#post-content-${id}`).textContent = post;
 document.querySelector(`#post-content-${id}`).style.display = "block";
 document.querySelector(`#post-edit-${id}`).style.display = "none";
 document.querySelector(`#post-edit-${id}`).value = post.trim(); 
  });
 }

views.py

@csrf_exempt
def edit_post(request, pk): #used to take in pk here also

    post = Post.objects.get(id=pk)  # was id=pk

    form = PostForm(instance=post)
    if request.method == "POST":
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            form.save()
          
            return JsonResponse({}, status=201) # this works to edit and save to db
    else:
        if request.method == "GET":           
            form = PostForm(instance=post)
            form_for_post = {'form': PostForm()}

            return render(request, "network/make_post.html", {
                "post": post,
                "form_for_post": form,
    })

相关的urls.py

path('edit_post/<str:pk>', views.edit_post, name="edit_post"),

相关 html - 第一部分是单击“编辑”时应打开的文本区域。 下一部分是编辑按钮。

span id="post-content-{{i.id}}" class="post">{{i.text}}</span> <br> 
                <textarea data-id="{{i.id}}" id="post-edit-{{i.id}}" 
style="display:none;" class="form-control textarea" row="3">{{i.text}}</textarea>

<button class="btn-btn primary" data-id="{{i.id}}" id="edit-btn-{{i.id}}" 
onclick="edit_handeler(this)" >Edit</button>

【问题讨论】:

    标签: javascript django django-forms javascript-objects fetch-api


    【解决方案1】:

    首先代码格式很乱,很难阅读,下次上传之前尝试使用 Prettier 或其他任何东西更好地格式化它。

    据我所知,onsubmit 监听器只能绑定到 &lt;form&gt; 元素,这是有道理的,您提交的不是 textarea,而是包含它的表单。 因此,您应该使用addEventListener 定位&lt;form&gt; 元素。

    此外,当调用侦听器时,浏览器会将 en event object 作为第一个参数插入其中。

    事件监听器只接受一个参数,即事件对象,它会自动传递给监听器,返回值被忽略。 MDN documentation

    如果你想访问元素的属性,你可以通过访问event.target来做到这一点

    做你需要的一种可能的方式: JS:

    function onsubmitHandler(event, url, ...others) {
      // prevents form from submitting and reloading the page
      event.preventDefault();
      // accessing element which caused firing this eventListener
      // in our case that is the form element
      let form = event.target;
      // now we need the textarea and its value
      let textarea = form.querySelector("textarea");
      let content = textarea.value;
    
      // other steps
      fetch(url, ...).then(res => ..)
    }
    

    HTML:

    <form onsubmit='onsubmitHandler(event, url, ...others)'> 
      <textarea>..</textarea>
      <button type="submit">..</button>
    </form>
    

    这样,按钮触发onsubmit事件,该事件被按钮所在的表单元素捕获。

    当然,您可以将 Django 模板中的值传递为:

    <form onsubmit='onsubmitHandler(event, {{ url }})'>
    

    关键点:

    • onsubmit 或 addEventListener("submit") 在表单本身上触发,因此它是事件的目标并重新加载页面 - 这是它的本机行为 - 您可以在侦听器回调函数中以编程方式停止 event.preventDefault()(onsubmitHandler 在我们的案例)

    请注意,提交事件会在元素本身上触发,而不是在任何元素上或元素内部。

    • 如果您使用&lt;form action="https://example.com" method="POST"&gt; 并且不附加任何事件侦听器,它将收集表单内的命名输入 ` 并将它们作为查询参数附加到操作 url => "https://example.com?car=汽车”并将带有该 URL 的 POST 请求发送到服务器。它不会等待任何内容并重新加载页面。

    我不是专家,我的课程和你一样,所以如果有错误或不清楚的地方,我很抱歉并随时提问。

    【讨论】:

      猜你喜欢
      • 2014-04-28
      • 2020-12-17
      • 2011-11-17
      • 2011-08-11
      • 1970-01-01
      • 2013-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      相关资源
      最近更新 更多