0

I'm trying to iterate over forms for likes with flask and AJAX. It works if there is just a single form and I use get element by id. What am I doing wrong in JS while iterating over the class?

HTML:

<form class="like_form" method="POST">
    <input type="hidden" name="user_id" value="{{session['logged_in']['id']}}">
    <input type="hidden" name="like_id" value="32">
    <input type="submit" class="small_submit" value="">
</form>

<form class="like_form" method="POST">
    <input type="hidden" name="user_id" value="{{session['logged_in']['id']}}">
    <input type="hidden" name="like_id" value="32">
    <input type="submit" class="small_submit" value="">
</form>
var like_form = document.getElementsByClassName('like_form');
for(var i = 0; i < like_form.length; i++){
    like_form[i].onsubmit = function(e){
        e.preventDefault();
        console.log("clicked form")
        var form = new FormData(like_form)
        fetch("http://localhost:5000/test/form", { method :'POST', body : form})
            .then( response => response.json() )
            .then( data => {
                console.log(data)
                console.log(data['stars'])
                const stars = document.getElementById("stars")
                stars.innerHTML = ` ${data['stars']}` 
            })
    }
}
xtina_lt
  • 29
  • 6
  • I'd start by switching from `var` to `let`. In general `let` is what you're looking for as `var` has different scopes. Secondly, are you getting any errors when you run this? – justanotherguy Mar 26 '22 at 20:03
  • Thanks that did not work. Yea. I'm getting the 405 method did not work. However it works when I do get element by id and there is only one form. – xtina_lt Mar 26 '22 at 20:06
  • Am I getting the looping over element by class concept okay? Or is the syntax different? – xtina_lt Mar 26 '22 at 20:07
  • Have you tried logging what the form data is? Maybe it's not what you expect it to be. – justanotherguy Mar 26 '22 at 20:11
  • `new FormData(like_form)` is passing a list of form elements, it needs to be `new FormData(like_form[i])` (with the [right value of `i`](https://stackoverflow.com/q/750486/1048572)) or just `new FormData(this)` – Bergi Mar 26 '22 at 20:26
  • Yea right now it isn't getting to the log. I log it after the fetch request. When I do it by element it logs correctly and changes everything correctly. – xtina_lt Mar 26 '22 at 20:41

2 Answers2

1

You need to get the form data of one form, not the collection of forms. To make it work I would suggest using a for..of loop, with let to get block scope:

for (let lform of like_form) {
    lform.onsubmit = function(e) {
        e.preventDefault();
        console.log("clicked form");
        var form = new FormData(lform); // <---

A second issue is document.getElementById("stars"). That element does not exist in your HTML. Moreover, if this is supposed to be an element that relates to the form (one for each form), then note that id attributes should be unique in HTML, so you should select such elements differently.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • That makes more since and I like how your loop syntax better. So maybe: – xtina_lt Mar 26 '22 at 20:21
  • Sorry I was trying to get the code from above onto the comments, but I couldn't get it correctly. Are you talking about like the code from the answer above? – xtina_lt Mar 26 '22 at 20:28
  • My comment was about the code you posted in comments, which is now gone, so I'll remove my comment too. – trincot Mar 26 '22 at 20:28
  • It is in my HTML its on my base that is exteding with JINJA and does work correctly with element. Therefore does exist. – xtina_lt Mar 26 '22 at 20:34
  • I do like your syntax. In essence should work. The concept is perfect. I am still getting the same error. Made the changes with the argument matching the variable used for the loop initiation. Also changed everything back to get elements by class name. Changed everything back to class. Going to keep playing with it. – xtina_lt Mar 26 '22 at 20:40
  • We got it!!!! I forgot to save XP. Silly me!!! Again love that loop. – xtina_lt Mar 26 '22 at 20:43
0

Ended up having to iterate through with the index :( Worked really well to change the like on the page too!! Just used the index for both the submit and changing the number on the page. See like_count[i].value

let like_form = document.getElementsByClassName('like_form');
let like_count = document.getElementsByClassName('like_count');
for(let i = 0; i < like_form.length; i++){
    like_form[i].onsubmit = function(e){
        e.preventDefault();
        console.log("clicked form")
        var form = new FormData(like_form[i])
        fetch("http://localhost:5000/test/form", { method :'POST', body : form})
            .then( response => response.json() )
            .then( data => {
                if (data['stars']){
                    console.log(data)
                    console.log(data['stars'])
                    const stars = document.getElementById("stars")
                    stars.innerHTML = ` ${data['stars']}` 
                    like_count[i].value = ` ${data['num']}`
                }
            })
        }
}
xtina_lt
  • 29
  • 6