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

[Help] Updating attribute values based on a change in a select dropdown

Hello, I've been having some trouble with a custom character sheet I've been working on. Basically, I have a <select> dropdown that let's you pick from different options, and I'd like to make it so depending on what option you pick, it would alter other values of attributes in the sheet.

Here's the <select> code:

<select name="attr_school" style="border: 1px solid black">
        <option value="pas">Pick a school</option>
        <option value="chron">Chronomancer</option>
        <option value="elem">Elementalist</option>
        <option value="ench">Enchanter</option>
        <option value="illu">Illusionist</option>
        <option value="necro">Necromancer</option>
        <option value="sigi">Sigilist</option>
        <option value="sooth">Soothsayer</option>
        <option value="summ">Summoner</option>
        <option value="thau">Thaumaturge</option>
        <option value="wit">Witch</option>
    </select>

And here's the values I'd like to modify depending on the selection with the above code:

<div class="sheet-tab-content sheet-tab5">
                <input type="number" name="attr_cm" value="0">
                <input type="number" name="attr_elm" value="0">
                <input type="number" name="attr_enm" value="0">
                <input type="number" name="attr_im" value="0">
                <input type="number" name="attr_nm" value="0">
                <input type="number" name="attr_sim" value="0">
                <input type="number" name="attr_som" value="0">
                <input type="number" name="attr_summ" value="0">
                <input type="number" name="attr_thm" value="0">
                <input type="number" name="attr_wim" value="0">
</div>

I will say, that I tried to simplify this, and hopefully that's not where I'm getting messed up. The above attribute values are added to about 80 different spells total, all within their respective school. So rather than trying to update 80 values, I figured it'd be easier to update 10 values, and then have the 80 spells each just add the modifier that has been altered. Like so:

<input style="width: 40px;height: 17px;float: right" type="number" name="attr_i1" value="10+@{im}" disabled="true" />

Any help would be appreciated. I've been going back and forth on it for days, breaking and unbreaking other parts of the code so I figured I'd get some help from people who knew what they were doing. 

August 09 (6 years ago)
The Aaron
Roll20 Production Team
API Scripter

You likely need a sheet worker that reacts to changes on school, something like:

on('change:school',(event)=>{ /* stuff */ });
That's what I've figured with looking around, but everytime I try to do that, I can't seem to get the values to update. 
August 09 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

This is a continuation of a thread posted over here: https://app.roll20.net/forum/permalink/7665677/

Post the code you've attempted. We'll be able to fix it. It's hard to know where to start without it.

Right, sorry. Here's the code of the whole javascript block, including the section that you gave me GiGs. I don't think I am adding it in the right spot because it keeps breaking the code you provided in the other thread. Not sure what I'm doing wrong.

<script type="text/worker">
    const soldier_stats = {
        no: {m: 0, f: 0, s: 0, a: 0, w: 0, hp_max: 0, hp: 0},
        wh: {m: 8, f: 1, s: 0, a: 10, w: 2, hp_max: 8, hp: 8},
        thug: {m: 6, f: 2, s: 0, a: 10, w: -1, hp_max: 10, hp: 10},
        thief: {m: 7, f: 1, s: 0, a: 10, w: 0, hp_max: 10, hp: 10},
        ar: {m: 6, f: 2, s: 2, a: 11, w: 0, hp_max: 10, hp: 10},
        xb: {m: 6, f: 2, s: 2, a: 11, w: 0, hp_max: 10, hp: 10},
        inf: {m: 6, f: 3, s: 0, a: 11, w: 0, hp_max: 10, hp: 10},
        tr: {m: 7, f: 2, s: 2, a: 11, w: 1, hp_max: 12, hp: 12},
        maa: {m: 6, f: 3, s: 0, a: 12, w: 1, hp_max: 12, hp: 12},
        th: {m: 7, f: 4, s: 0, a: 11, w: 2, hp_max: 12, hp: 12},
        kn: {m: 5, f: 4, s: 0, a: 13, w: 1, hp_max: 12, hp: 12},
        te: {m: 5, f: 4, s: 0, a: 12, w: 1, hp_max: 12, hp: 12},
        ra: {m: 7, f: 2, s: 2, a: 11, w: 2, hp_max: 12, hp: 12},
        ba: {m: 6, f: 4, s: 0, a: 10, w: 3, hp_max: 14, hp: 14},
        ap: {m: 6, f: 0, s: 0, a: 10, w: 0, hp_max: 12, hp: 12},
        mm: {m: 5, f: 2, s: 3, a: 12, w: 1, hp_max: 12, hp: 12},
    };

    const soldier_cells = ['s1', 's2', 's3', 's4', 's5', 's6', 's7', 's8' ]; // add in as many as you need.

    soldier_cells.forEach(soldier => {
        on(`change:${soldier}`, function () {
            getAttrs([soldier], function (values) {
                const which = values[soldier];
                const stats = soldier_stats[which];
                const settings = {};
                Object.keys(stats).forEach(key => {
                    settings[`${soldier}${key}`] = stats[key];
                });
                setAttrs(settings);
            });
        });
    });
    
    on('change:school', function() {
        getAttrs(["school", "cm", "elm", "enm", "im", "nm", "sim", "som", "summ", "thm", "wim"], function(values) {
            let s = 'attr_school'
            if (s === 'chron') {
                setAttrs({
                    "cm": "0"
                    "elm": "2"
                    "enm": "6"
                    "im": "4"
                    "nm": "2"
                    "sim": "4"
                    "som": "2"
                    "summ": "4"
                    "thm": "4"
                    "wim": "4"
                });
            }};
        });
    });
</script>

As far as I understand it, I need to get the values of the selection that uses the on(change) as well as all the modifier values that I want to be altered based off of the selection. I tried to make it so if the selected option was 'x', then it would setAttrs to all the modifiers accordingly. I didn't keep going with the other options of schools from the select, because I couldn't ever get one of them to work. 

Thanks for taking a look guys. I really appreciate it.

August 09 (6 years ago)

Edited August 09 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

You have a couple of errors. "attr_" is not part of the attribute name. If you have an input with 

name="attr_school"

Also to get an attributes values, you need to use the values object, like so

let school = values.school;

you access that with just "school" not "attr_school".

In your getAttrs line, you grab all the attribute values (cm, elm, etc) but you dont need to. You are going to be overwriting those values, so the only one you actually need to read from the sheet is school.

Also your setAttrs has an error. you need a comma after every row except the last:

setAttrs({
                    "cm": "0",
                    "elm": "2",
                    "enm": "6",
                    "im": "4",
                    "nm": "2",
                    "sim": "4",
                    "som": "2",
                    "summ": "4",
                    "thm": "4",
                    "wim": "4"
                });

The construction you are using (putting them in if statements like that) will work, but it's not the best way to approach it. If you wanted to reuse my code, you could do it like this:

 const schools_stats = {
none: {cm: 0, elm: 0, enm: 0, im: 0, nm: 0, sim: 0, som: 0, summ: 0, thm: 0, wim: 0},
        chron: {cm: 0, elm: 2, enm: 6, im: 4, nm: 2, sim: 4, som: 2, summ: 4, thm: 4, wim: 4},
};
on('change:school', function() {
getAttrs(["school"], function(values) {        
           let s = values.school || 'none';
let stats = schools_stats[s]
setAttrs(stats);
});
});

This is a bit complicated, but replaces your if statement with a much shorter code, and also handles the situation of not having a school selected or entering the wrong name.

All you need to do is to fill in the school_stats section with the correct values. You've done that when you did the soldiers last time.

That did the trick, thanks GiGs :) I don't know what my issues were before when I tried tweaking what you gave me because it would break the code for the soldier selection everytime, but it's all working and I can rest easy! Thank you so much for the help, this was my first time with html/css/java so it means a lot.

August 09 (6 years ago)

Edited August 09 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

You're welcome! Sorry i forgot about responding to the other thread :)

If you have really bad syntax in one worker, it can break the entire script block. My guess is that one of those errors was serious enough to cause all sheet workers to stop working. Most likely the setAttrs error.

August 09 (6 years ago)
GiGs
Pro
Sheet Author
API Scripter

Oh, while I remember: a lot of your attribute names are things like "em" , "nm", "no" etc. There's nothing wrong with doing this, except you don't have to do that. You can use longer, descriptive words, and it's better for readability. Instead of "chron" you could use "chronomancer", "elem" => "elemantalist" and so on.

Just keep them as one word, or join multiple words with an under_score like_this, and your sheet will be a lot more readable. When players call an attribute in a macro with something like @(school} they'll know what it means. 


I thought about that honestly, I just figured with writing the code it'd be easier to make it shorter, but if that doesn't help make the game run smoother, than I should absolutely do that.