Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

getting ids of a repeating section

December 19 (4 years ago)

I'm running an experiment to access all the values of rows in a repeating section. I've found numerous examples showing how to iterate over the items in the repeating section and access the row id's, but I'm having trouble implementing it as it doesn't appear to ever execute. Using this basic call to test it out, the code in getSectionIDs never runs.

for the test, i have a checkbox that runs when changed and updates a text input. the input updates jsut fine when the change function is called, but it never reaches the line that updates the text for the input inside the getSectionIDs call. I have the code to iterate over the repeating section items once getsectionid's executes, but it never seems to (hence this test to confirm that. What am I doing wrong here?

on("change:listitemscheckbox", function() {

  let weaponlist = "Start function. ";

  getSectionIDs('weapons', function (ids) {

     weaponlist = weaponlist + ' Run code for section IDs.';

});

 setAttrs({['theweaponstring']: String(weaponlist)});

});

December 19 (4 years ago)

Edited December 19 (4 years ago)
Oosh
Sheet Author
API Scripter

Just to double check the repeating section name is correct (you have singular 'weapon' in your other references), so @{selected|repeating_weapons_$0_<attr_name>} will successfully return a value if pasted in chat with a valid attribute name?


If that's correct, what's the actual code you're running? Are you looping through the array? Obviously 'Run code for section IDs' isn't it, that isn't going to do a whole lot :)

Your first line in the callback probably wants to be a (for) loop or a forEach, e.g.:

ids.forEach(id => {
// if this row passes test, push a value to weaponList
})

Hard to tell without some actual code though!

December 20 (4 years ago)

Edited December 20 (4 years ago)

Here's a simple test sheet that I'm using to try to work it out:


                    <fieldset class="repeating_weapons">

                        <select class="weapontable" name="attr_names" value="name">

                            <option>Dagger</option>

                            <option>Sword</option>

                            <option>Bow</option>

                        </select>

                       </select>

                        <input type="text" name="attr_wpnname" value="-"  readonly />

                        <input type="text"  name="attr_damage" value="-"  readonly />

                        <input type="text" name="attr_style" value="-"  readonly />

                    </fieldset>


                    <input type="text" name="attr_theteststring" value=""/>

                    

 <script type="text/worker">                   

                    

on ("change:repeating_weapons:names", function(eventInfo) {

    let RID = eventInfo.sourceAttribute.slice(18,38);

    getAttrs(['repeating_weapons_names'], function(values) {

        let dagger =           {name:"Dagger",    damage:"4",   wpnstyle:"P" };

        let sword =           {name:"Sword",    damage:"8",   wpnstyle:"S" };

        let bow =           {name:"Bow",    damage:"6",   wpnstyle:"R" };


        let wps = [dagger, sword, bow];


        for (i = 0 ; i < wps.length ; i++) {

            if (wps[i].name == values['repeating_weapons_names']) {

                setAttrs({['repeating_weapons_'+RID+'_style']: String(wps[i].wpnstyle),

                          ['repeating_weapons_'+RID+'_damage']: String(wps[i].damage),

                          ['repeating_weapons_'+RID+'_wpnname']: String(wps[i].name)});

            }

        }

    })

})

                  on("sheet:opened", function() {

    

    let weaponlist = "";

    

    getSectionIDs('weapons', function (ids) {

    

                ids.forEach(id => {

                   weaponlist = weaponlist + " " + ['repeating_weapons_${id}_wpnname'];

                });

            });

    

    

        setAttrs({['theteststring']: String(weaponlist)});

    

    });

</script>


December 21 (4 years ago)
Oosh
Sheet Author
API Scripter

Ok, I'm not a sheet author, so my advice may not be entirely accurate, but I think the main issue is that you need a getAttrs in the second function there. I think (I could be wrong) you can remove the rowId from your first function too - both getAttrs and setAttrs can function without it provided they're working in the same row that triggered the event. So... you can try something like this (untested, I don't have a Pro sub so no sheet sandbox):

on ("change:repeating_weapons:names", function(eventInfo) {

getAttrs(['repeating_weapons_names'], function(values) {
let dagger = {name:"Dagger", damage:"4", wpnstyle:"P" };
let sword = {name:"Sword", damage:"8", wpnstyle:"S" };
let bow = {name:"Bow", damage:"6", wpnstyle:"R" };

let wps = [dagger, sword, bow];

for (let i = 0 ; i < wps.length ; i++) {
if (wps[i].name == values['repeating_weapons_names']) {
setAttrs({['repeating_weapons_style']: String(wps[i].wpnstyle),
['repeating_weapons_damage']: String(wps[i].damage),
['repeating_weapons_wpnname']: String(wps[i].name)});

}
}
})
})

on("sheet:opened", function() {
let weaponlist = '';
getSectionIDs('weapons', function (ids) {
let attrInput = ids.map((id) => `repeating_weapons_${id}_wpnname`)
getAttrs(attrInput, function(values) {
for (let x in values) {
weaponlist += `${values[x]} `;
}
});
});
setAttrs({['theteststring']: String(weaponlist)});
});


There's also a slightly more efficient way of building out a string with the += operator, to save you some repetition.

You generally want to minimise your use of getAttrs and setAttrs in sheetworkers, so I've used .map() to build an array of the repeating attributes to grab once, rather than using a .forEach loop and a getAttrs call per row.

See how you go with that, hopefully I didn't break anything that was already working :)

December 21 (4 years ago)

Huh. this turned out to be interesting:

weaponlist would still come up as an empty string, but moving the setAttrs function into the for loop produces the desired result, even though it's not the way I would think it should be done. I think I can work with it though to achieve the final result I'm after. Thanks for the help!

      for (let x in values) {
                   weaponlist += `${values[x]} `;
                   setAttrs({['theteststring']: String(weaponlist)});
                }


December 21 (4 years ago)
Oosh
Sheet Author
API Scripter

Ah yep, my bad. I'd say that's an async issue, setAttrs is running before the (for) loop completes. The setAttrs should go outside the (for) loop, but inside the getAttrs callback (I think!). That way it only runs once (much more efficient in terms of sheet lag) but there shouldn't be any async dramas inside the same callback (I think):

on("sheet:opened", function() {
let weaponlist = '';
getSectionIDs('weapons', function (ids) {
let attrInput = ids.map((id) => `repeating_weapons_${id}_wpnname`)
getAttrs(attrInput, function(values) {
for (let x in values) {
weaponlist += `${values[x]} `;
}
setAttrs({['theteststring']: String(weaponlist)});
});
});
});


Hopefully that also works, since you generally don't want to be putting getAttrs or setAttrs inside loops - if you make a habit of it, the sheet will become very laggy very quickly (I'm led to believe).

December 21 (4 years ago)

I'll do some more experimenting, but at least now I have something working to build from. Again, thanks for the help!