Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Alternative to delegate() in Javascript to add onClick AddListener to buttons in loop

Discussion in 'Scripting' started by sudhaMR, Jul 11, 2015.

  1. sudhaMR

    sudhaMR

    Joined:
    Jun 17, 2015
    Posts:
    12
    I noticed that while I instantiate a button prefab in a loop and attach onClick listener to it, then only the last iterated loop's value is passed by the button.
    I searched and found that this is resolved by using delegate function in C# and as wrapper functions in Javascript. I tried doing them, but they still only take the value from the last iteration.

    Code (JavaScript):
    1. @SerializeField
    2. var buttonPrefab:GameObject;
    3. @SerializeField
    4. var menuPanel:Transform ;
    5. public var button :GameObject;
    6. function Start () {  
    7.     for(j = 0; j < countJSON;j++)              
    8.     {  
    9.         descriptionMixed = jsonBooks["details"][j]["title"].ToString();                
    10.         button  = Instantiate (buttonPrefab);  
    11.         button.GetComponentInChildren(UnityEngine.UI.Button).name = descriptionMixed;
    12.  
    13.         var sendOnClick:String = descriptionMixed;
    14.  
    15.         var b : Button = button.GetComponent(UnityEngine.UI.Button);
    16.      
    17.         b.onClick.AddListener(function (){
    18.                                             function (){                                                      
    19.                                                              ButtonClicked(sendOnClick);
    20.                                                       };
    21.                                         }
    22.                             ());
    23.        } // end of for
    24.  
    25. }//end of start
    26.  
    27. function ButtonClicked(title)
    28. {  
    29.     populate.animalName = title;
    30.     Debug.Log("onclick"+title); //Always returns the last iterated variable's value.
    31.     Application.LoadLevel("ATemp");
    32. }
    33.  
    Is there a way to implement this? I really can't change my entire code C#. This is just an excerpt from the entire code. And is sort of the last missing piece of the application!
    I basically want the descriptionMixed or the button.name property of the button clicked to be passed on to the ButtonClicked() function. Any other suggestion to implement this in another way is also welcome :)
     
    Last edited: Jul 11, 2015
  2. chubbspet

    chubbspet

    Joined:
    Feb 18, 2010
    Posts:
    1,220
  3. sudhaMR

    sudhaMR

    Joined:
    Jun 17, 2015
    Posts:
    12
    Thanks for the response! Invoke invokes a function after some time t seconds. I do not see how it helps in not returning the last value of the loop when clicked on some nth button instantiated previously.

    Let us say I have 3 buttons instantiated in a loop and attached an onClick to it to return the name property.
    B1.name = abc
    B2.name = def
    B3.name = ghi

    After creation ends, if I click B1 or B2, the onClick returns name of B3 i.e, "ghi" and not "abc" or "def".
     
  4. sudhaMR

    sudhaMR

    Joined:
    Jun 17, 2015
    Posts:
    12
    So, I figured out what the problem was.
    Passing the value to be preserved as a parameter helps. It goes like this:
    • I made descriptionMixed store in a variable declared inside the loop, like already in the code at line 13.
    • Then passed that as a parameter to the wrapper function, like this:
    Code (JavaScript):
    1. b.onClick.AddListener((function (sendOnClick,ID){
    2.                                              function (){      Debug.Log("listener:"+sendOnClick+"id:"+ID);
    3.                                                                    ButtonClicked(sendOnClick,ID);  
    4.                                                                                                            
    5.                                                        };
    6.                                         })
    7.                              (sendOnClick,animalID));    
    • The ButtonClicked function defines what to do with the data of the button pressed. ID is just another parameter my function accepts.