2

I'm learning to code and i've come across a probably quite easy problem to solve.

I make a request from the database, that returns a number of users. For each user i create a few input fields like name, email etc.

Now what i want to do is use the same php variable (that contains the number of users), to create or repeat a function x times.

This is what i've tried so far.

var j = 0;

while (j <= i) { //i is the variable passed from php, containing the number of useres

    j++;

    $('#btnEdit'+j).click(function() {

        $("#prename"+j).removeAttr('disabled');
        $("#surname"+j).removeAttr('disabled');
        $("#function"+j).removeAttr('disabled');
        $("#prefix"+j).removeAttr('disabled');
        $("#phone_number"+j).removeAttr('disabled');
        $("#email"+j).removeAttr('disabled');


    });


}

The HTML looks something like this:

Input

<label>Prename</label>
<input name="prename" id="prename<?php echo $i; ?>" value="<?php echo $row['db_prename_value']; ?>" maxlength="100" type="text" placeholder="Prename" disabled="disabled" />

Button

<input type="button" id="btnEdit<?php echo $i; ?>"
name="button<?php echo $i; ?>" value="Edit"></input>

To give a short explanation:

If the database returns 2 users, all the above fields are created for 2 users in php. User 1 will have prename1, surname1 etc. while user 2 will have prename2, surname2 and so on.

I won't know how many users get returned by the database so i can't just manually create the above snippet a set amount of times.

To clarify, i've already passed the variable from php to javascript (variable i). The question is how to repeat the javascript function x times, as the snippet i've posted is not working.

As far as my understanding goes, what my code does is iterate through the while loop x amount of times, but stops at this line, since the button is not being clicked.

    $('#btnEdit'+j).click(function() {

Maybe i'm just confused about how to do what i'm trying to do.

Let's make an example. If the variable i is 2, i want the loop to create 2 functions, the first function has to be executed when the button with the id btnEdit1 is being clicked, the second function needs to execute when a button with the id btnEdit2 is being clicked etc.

Thanks

zoefrankie
  • 29
  • 1
  • 7
  • Can you share the HTML? You could use DOM relationship – Satpal Feb 21 '18 at 12:51
  • You can create a function that receives the ID as argument. Then at that click handler, call the function with the j argument. – KarelG Feb 21 '18 at 12:52
  • This code will create multiple functions. But since all of them use the same global `j` variable, all the functions will do the same thing. When the loop finishes `j == i`. – Håken Lid Feb 21 '18 at 12:52
  • 3
    Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Teemu Feb 21 '18 at 12:54
  • @HåkenLid But does the code actually create the functions? When using the debugger and setting a breakpoint at the start of the loop it only iterates to the " $('#btnEdit'+j).click(function() { " line, and then jumps back to the start. – zoefrankie Feb 21 '18 at 12:56
  • You create the function as a single statement. The debugger treats it as one line. `$('#btnEdit'+j)` will be evaluated in the loop, but the function body will not be evaluated until you click a button. At that time `j` will be the same for every function. – Håken Lid Feb 21 '18 at 12:59
  • Yes. That's what I would expect. But there might be some other bug. Your code in the question isn't really [mcve], so I can't reproduce your problem. – Håken Lid Feb 21 '18 at 13:08
  • @HåkenLid Just tried. Both buttons execute the function for the same user (User 2 in this case since the loop iterates twice). How would i fix this? As far as i understand i'm getting 2 functions that both start with the line $('#btnEdit2'), instead of $('#btnEdit1') and $('#btnEdit2') – zoefrankie Feb 21 '18 at 13:11
  • Read the duplicate question. What you can do is to create a closure with a local variable instead of the global scope j. – Håken Lid Feb 21 '18 at 13:16
  • @HåkenLid I've read through it but didn't really get what it does. I tried one of the answers with "bind" but it didn't quite work. It still would only execute one function, as if there was only one button. – zoefrankie Feb 21 '18 at 13:43
  • There are many ways to skin a cat. In this case, you can do it without closures as well, as suggested by the two answers. If you want to use `bind`, you have to make sure that the inner function takes the id value as an argument. `$('#btnEdit'+j).click((function(index){$("#prename"+index) [...] }).bind(null, j))` – Håken Lid Feb 21 '18 at 15:55
  • @HåkenLid I think i understand what i did wrong. Well, i'm using the solution Satpal provided, but thanks for clarifying. – zoefrankie Feb 21 '18 at 16:05

2 Answers2

2

Instead of creating multiple function I would recommend you to create single function.

Use custom data-* attribute to persist php variable <?php echo $i; ?> with edit button which can later be fetched using .data(key).

To attach event handler Class Selector (“.class”) to target the elements and using Event Delegation create a single method.

<input type="button" class="btnEdit" data-id="<?php echo $i; ?>" name="button<?php echo $i; ?>" value="Edit"></input>

Script

$(document).on('click', '.btnEdit', function(){
    var j = $(this).data('id');
    $("#prename"+j).removeAttr('disabled');
    $("#surname"+j).removeAttr('disabled');
    $("#function"+j).removeAttr('disabled');
    $("#prefix"+j).removeAttr('disabled');
    $("#phone_number"+j).removeAttr('disabled');
    $("#email"+j).removeAttr('disabled');
})
Satpal
  • 132,252
  • 13
  • 159
  • 168
  • I'm not quite sure i understand what this does. Could you go into more detail? If i use data-id="", i won't all the input fields of the first user have data-id=1 ? – zoefrankie Feb 21 '18 at 13:06
  • @zoefrankie, I am persisting the same php variable ``with the `btnEdit` element using `data-id=""`, which is fetched later and used to target the desired element – Satpal Feb 21 '18 at 13:09
  • But i iterate through a php loop x amount of times to create the input fields. If i replace the id with data-id="", won't all the fields of the first user have data-id=1? I'm confused since you removed the id=prename tag, but you're still trying to remove the attribute in js using the id. Isn't #prename+j undefined in this case? – zoefrankie Feb 21 '18 at 13:19
  • @zoefrankiem, I removed `id="btnEdit"` with edit button as it was of no use. If you want you can keep it – Satpal Feb 21 '18 at 13:20
  • My bad, i actually thought you were changing the input type text. That being said i'm still not really sure what the code does. What is this line for? var j = $(this).data('id'); And if you use the class to execute the function, won't the Button 2 execute the exact same function? – zoefrankie Feb 21 '18 at 13:24
  • @zoefrankie, Button 2 will execute the exact same function but with different `this` so `var j = $(this).data('id');` will be different thus it will target different element – Satpal Feb 21 '18 at 13:27
  • I've tried and this works. After thinking about your code i also understand what it does. Thanks – zoefrankie Feb 21 '18 at 16:03
0

Why you need this?

You can directly write with an onClick event in input as well with the parameter of your id (which means your i value) .

Please take this answer as a key idea

<input type="button" id="btnEdit<?php echo $i; ?>"
name="button<?php echo $i; ?>" onClick="btnEdit(?php echo $i; ?)" value="Edit"></input>

function btnEdit(id)
{
$("#prename"+id).removeAttr('disabled');
        $("#surname"+id).removeAttr('disabled');
        $("#function"+id).removeAttr('disabled');
        $("#prefix"+id).removeAttr('disabled');
        $("#phone_number"+id).removeAttr('disabled');
        $("#email"+id).removeAttr('disabled');
}

Note: I don't have experience in php . but this is common idea only

Ramesh Rajendran
  • 37,412
  • 45
  • 153
  • 234