skip to Main Content

I am trying to calculate the value of some input field in my Django template using javascript (onkeyup=(), the form is in a loop e.g {% for p in prediction %} {% endfor %}.

I have this simple line to grab the input values (NOTE: They are in a loop)

   let stake_amount_input = document.querySelector("#amount").value
   let shares_amount_input = document.querySelector("#shares").value

Based on the fact that I have all these functions in a Django loop, am I not supposed to get all the input field values when I calculate the other objects in the loop?

Based on the fact that I have all these functions in a Django loop, am I not supposed to get all the odds when I console.log(odds)

{% for p in prediction.prediction_data.all %}
  <form action="#" method="POST">
     <input type="number" value="" name="amount" id="amount" class="shares" onkeyup="CalculateNewBalance()">
     <input type="number" value="" name="shares" id="shares" class="shares" onkeyup="CalculateNewBalance()">

    <script>
      function CalculateNewBalance(){
          let stake_amount_input = document.querySelector(".amount").value
          let shares_amount_input = document.querySelector(".shares").value
          let potential_win = document.querySelector(".potential-win")

          let potential_win_value = parseFloat(stake_amount_input) * parseInt(shares_amount_input)
          potential_win.innerHTML = "$" + potential_win_value
          
          // if the potential_win innerHTML shows Nan, then i want to change the innerHTML to $0.00, but this is not working too
         if (potential_win === isNan) {
             potential_win.innerHTML = "$0.00"
         }

                                                        
    </script>
    </form>
{% endfor %}

enter image description here
enter image description here

EDIT:
My template

<div class="mid-area">
    <div class="single-area">
        <div class="item-title d-flex align-items-center justify-content-between">
            <span>Choose Stake Amount</span>
        </div>
        <div class="d-flex in-dec-val">
            <input type="number" required value="{{ p.amount }}" name="amount" placeholder="amount" class="shares" />

            <div class="btn-area">
                <button class="plus" type="button">
                    <img src="{% static 'assets/images/icon/up-arrow.png' %}" alt="icon" />
                </button>
                <button class="minus" type="button">
                    <img src="{% static 'assets/images/icon/down-arrow.png' %}" alt="icon" />
                </button>
            </div>
        </div>

        <p id="error-div" class="mt-2"></p>
    </div>
    <div class="single-area quick-amounts"></div>
    <div class="single-area quick-amounts">
        <div class="item-title d-flex align-items-center">
            <p>Choose <b>Shares</b> Amount</p>
        </div>
        <div class="d-flex in-dec-val">
            <input type="number" required value="1" name="shares" placeholder="shares" class="shares" />

            <div class="btn-area">
                <button class="pldus" type="button">
                    <img src="{% static 'assets/images/icon/up-arrow.png' %}" alt="icon" />
                </button>
                <button class="mindus" type="button">
                    <img src="{% static 'assets/images/icon/down-arrow.png' %}" alt="icon" />
                </button>
            </div>
        </div>
    </div>

    <div class="single-area smart-value">
        <div class="item-title d-flex align-items-center">
            <p class="mdr text-capitalize">Potential win</p>
        </div>
        <div class="contact-val d-flex align-items-center"><span style="font-size: 24px;" class="potential-win">$0.00</span><br /></div>
    </div>
</div>

2

Answers


  1. You have to add unique name every time you loop. Variable names and Id’s should be unique. For this you have to add counter or unique values. Check this answer for how to add counter.

    {% for p in prediction.prediction_data.all %}
      
      <form action="#" method="POST">
         <input type="number" value="" name="amount" id="amount{{ forloop.counter }}" class="shares" onkeyup="CalculateNewBalance()">
         <input type="number" value="" name="shares" id="shares{{ forloop.counter }}" class="shares" onkeyup="CalculateNewBalance()">
    
        <script>
          function CalculateNewBalance(){
              let stake_amount_input{{ forloop.counter }} = document.querySelector(".amount{{ forloop.counter }}").value
              let shares_amount_input{{ forloop.counter }} = document.querySelector(".shares{{ forloop.counter }}").value
              let potential_win{{ forloop.counter }} = document.querySelector(".potential-win{{ forloop.counter }}")
    
              let potential_win_value{{ forloop.counter }} = parseFloat(stake_amount_input{{ forloop.counter }}) * parseInt(shares_amount_input{{ forloop.counter }})
              potential_win{{ forloop.counter }}.innerHTML = "$" + potential_win_value{{ forloop.counter }}
              
              // if the potential_win innerHTML shows Nan, then i want to change the innerHTML to $0.00, but this is not working too
             if (potential_win{{ forloop.counter }} === isNan) {
                 potential_win{{ forloop.counter }}.innerHTML = "$0.00"
             }
    
                                                            
        </script>
        </form>
    {% endfor %}
    

    {{ forloop.counter }} returns a list of numbers from 1 to number, until for loop runs.

    The This would make every id unique and every variable unique. For example, when the loop runs

    for first time:

    let potential_win1 = document.querySelector(".potential-win1").value
    

    for second time:

    let potential_win2 = document.querySelector(".potential-win2").value
    

    and so on.

    Login or Signup to reply.
  2. Instead of putting whole form & script inside loop just add input fields inside loop and then either set event on each element inside loop or add event listener programmatically. I’ll show programmatic approch.

    <form action="#" method="POST">
    {% for p in prediction.prediction_data.all %}
         <input type="number" value="" name="amount" class="shares" onkeyup="CalculateNewBalance()">
         <input type="number" value="" name="shares" class="shares" onkeyup="CalculateNewBalance()">
    {% endfor %}
    </form>
    
     let inputs = document.querySelectorAll('input');
    function CalculateNewBalance(e) {
        let target = e.target
        let potential_win_value;
        let potential_win;
    
        if (target.nextElementSibling.classList.contains('potential-win')) {
            potential_win = target.nextElementSibling
        } else {
            potential_win = target.nextElementSibling.nextElementSibling
        }
    
        if (target.nextElementSibling.classList.contains('shares')) {
            potential_win_value = parseFloat(target.nextElementSibling.value) * parseInt(target.value)
        } else {
            potential_win_value = parseFloat(target.previousElementSibling.value) * parseInt(target.value)
        }
    
        potential_win.innerHTML = "$" + potential_win_value
    
        if (potential_win.innerHTML == '$NaN') potential_win.innerHTML = '$0.00'
    }
    
    ['input', 'change'].forEach(evt => {
        inputs.forEach(input => input.addEventListener(evt, CalculateNewBalance, false))
    });
    

    Here is working example

     let inputs = document.querySelectorAll('input');
            function CalculateNewBalance(e) {
                let target = e.target
                let potential_win_value;
                let potential_win;
    
                if (target.nextElementSibling.classList.contains('potential-win')) {
                    potential_win = target.nextElementSibling
                } else {
                    potential_win = target.nextElementSibling.nextElementSibling
                }
    
                if (target.nextElementSibling.classList.contains('shares')) {
                    potential_win_value = parseFloat(target.nextElementSibling.value) * parseInt(target.value)
                } else {
                    potential_win_value = parseFloat(target.previousElementSibling.value) * parseInt(target.value)
                }
    
                potential_win.innerHTML = "$" + potential_win_value
    
                if (potential_win.innerHTML == '$NaN') potential_win.innerHTML = '$0.00'
            }
            
            ['input','change'].forEach( evt => {
                inputs.forEach(input => input.addEventListener(evt, CalculateNewBalance, false))
            }
            );
    <form action="#" method="POST">
            <input type="number" value="" name="amount" placeholder="amount" class="shares">
            <input type="number" value="" name="shares" placeholder="shares" class="shares">
            <span class="potential-win">$0.00</span><br />
    
            <input type="number" value="" name="amount" placeholder="amount" class="shares">
            <input type="number" value="" name="shares" placeholder="shares" class="shares">
            <span class="potential-win">$0.00</span><br />
    
            <input type="number" value="" name="amount" placeholder="amount" class="shares">
            <input type="number" value="" name="shares" placeholder="shares" class="shares">
            <span class="potential-win">$0.00</span><br />
        </form>

    Note:

    1. If you’re creating application which includes real transactions & calculations of amount you should not rely on client side calculation
      handle it on server side.
    2. Don’t use ID inside loop it shold be unique
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search