Varsuuk
June 30th, 2023, 15:53
I went to combine various components across 3 comboboxes. The idea if you choose a race in the combobox, it invalidates sub/half-race combos (assuming it changed) and populates the next one down with proper sub or half-races.
This worked fine. So I went to add code to populate the "Race" box on the header.
EDIT: Clarification of the TLDR; question:
I always understood "getValue" would return nil of the node was not found, or the default specified if you passed that. But I am not passing a 3rd argument and still getting "", instead of the nil I expected, back on these strings - AS FAR AS I CAN SEE anyway...
function getValue(sourcenode, [subpath], [default])
Returns the value contained in the specified database node. The return value(s) vary depending on the type of the node. If the node does not exist or if the node is a non-value type, then the default values passed in will be returned or nil if no default values are specified.
When I was seeing the Race field fill with "()", I thought the only way that is possible is if the 2 or 3 values were non-nil. But... the first time, they have to be nil (because there are no nodes for subrace/halfrace yet) I verified this with /save and looking at the DB.
So I added the prints and saw what looked like "" values returned vs string
New log:
[6/30/2023 10:19:06 AM] s'updateRace' | databasenode = { charsheet.id-00004 }
[6/30/2023 10:19:06 AM] s'Race:' | s''
[6/30/2023 10:19:06 AM] s'Subrace:' | s''
[6/30/2023 10:19:06 AM] s'Halface:' | s''
[6/30/2023 10:19:06 AM] s'formatRaceString' | s'' | s'' | s''
[6/30/2023 10:19:06 AM] s' ()'
[6/30/2023 10:19:06 AM] s'updateRace' | databasenode = { charsheet.id-00004 }
[6/30/2023 10:19:06 AM] s'Race:' | s'Elf'
[6/30/2023 10:19:06 AM] s'Subrace:' | s''
[6/30/2023 10:19:06 AM] s'Halface:' | s''
[6/30/2023 10:19:06 AM] s'formatRaceString' | s'Elf' | s'' | s''
[6/30/2023 10:19:06 AM] s' ()'
This is what it looks like in the DB after selecting Elf on combo but the other 2 are still empty:
<race>
<baserace type="string">Elf</baserace>
<racevalue type="string">elf</racevalue>
</race>
(EDIT: After seeing it saves as "baserace" and "racevalue" I made the "source" property match the "name" so the autonaming in combobox would be consistant, the nodes are now "baserace" and "baseracevalue", it doesn't affect it but in case this was misleading)
Code to generate:
...
local nodeChar = getDatabaseNode()
Debug.console("updateRace", nodeChar)
Debug.console("Race:", DB.getValue(nodeChar, "race.baserace"))
Debug.console("Subrace:", DB.getValue(nodeChar, "race.subrace"))
Debug.console("Halface:", DB.getValue(nodeChar, "race.halfrace"))
local race_display = Race.formatRaceString(
DB.getValue(nodeChar, "race.baserace"),
DB.getValue(nodeChar, "race.subrace"),
DB.getValue(nodeChar, "race.halfrace"))
Debug.console(race_display)
DB.setValue(nodeChar, "race_string", "string", race_display)
...
The formatting thing (changing it to: if xxx == "" worked and proper string is generated. But...?)
function formatRaceString(race, subrace, halfrace)
Debug.console("formatRaceString", race, subrace, halfrace)
if race == nil then
return ""
end
if subrace == nil then
return race
elseif halfrace == nil then
return subrace
else
return subrace .. " (" .. halfrace .. ")"
end
end
Bonus Question:
Is there an opinion on "Best practices"? If the popup was a modal dialog (something which I will look to see if there is an option in what I open, I seem to recall seeing this before...), I'd simply do the RACE update on "onClose()". I currently do it on the onValueChanged() of any of the 3 race subfields since the user can leave that window open - again, I suspect that is my FIRST problem - picking wrong option there and I will fix it if there is a modal version to use, but still worth asking. Or is it OK to add a "button" to "Apply" changes or "Cancel" as it were and do the caculation/string-concat there?
This worked fine. So I went to add code to populate the "Race" box on the header.
EDIT: Clarification of the TLDR; question:
I always understood "getValue" would return nil of the node was not found, or the default specified if you passed that. But I am not passing a 3rd argument and still getting "", instead of the nil I expected, back on these strings - AS FAR AS I CAN SEE anyway...
function getValue(sourcenode, [subpath], [default])
Returns the value contained in the specified database node. The return value(s) vary depending on the type of the node. If the node does not exist or if the node is a non-value type, then the default values passed in will be returned or nil if no default values are specified.
When I was seeing the Race field fill with "()", I thought the only way that is possible is if the 2 or 3 values were non-nil. But... the first time, they have to be nil (because there are no nodes for subrace/halfrace yet) I verified this with /save and looking at the DB.
So I added the prints and saw what looked like "" values returned vs string
New log:
[6/30/2023 10:19:06 AM] s'updateRace' | databasenode = { charsheet.id-00004 }
[6/30/2023 10:19:06 AM] s'Race:' | s''
[6/30/2023 10:19:06 AM] s'Subrace:' | s''
[6/30/2023 10:19:06 AM] s'Halface:' | s''
[6/30/2023 10:19:06 AM] s'formatRaceString' | s'' | s'' | s''
[6/30/2023 10:19:06 AM] s' ()'
[6/30/2023 10:19:06 AM] s'updateRace' | databasenode = { charsheet.id-00004 }
[6/30/2023 10:19:06 AM] s'Race:' | s'Elf'
[6/30/2023 10:19:06 AM] s'Subrace:' | s''
[6/30/2023 10:19:06 AM] s'Halface:' | s''
[6/30/2023 10:19:06 AM] s'formatRaceString' | s'Elf' | s'' | s''
[6/30/2023 10:19:06 AM] s' ()'
This is what it looks like in the DB after selecting Elf on combo but the other 2 are still empty:
<race>
<baserace type="string">Elf</baserace>
<racevalue type="string">elf</racevalue>
</race>
(EDIT: After seeing it saves as "baserace" and "racevalue" I made the "source" property match the "name" so the autonaming in combobox would be consistant, the nodes are now "baserace" and "baseracevalue", it doesn't affect it but in case this was misleading)
Code to generate:
...
local nodeChar = getDatabaseNode()
Debug.console("updateRace", nodeChar)
Debug.console("Race:", DB.getValue(nodeChar, "race.baserace"))
Debug.console("Subrace:", DB.getValue(nodeChar, "race.subrace"))
Debug.console("Halface:", DB.getValue(nodeChar, "race.halfrace"))
local race_display = Race.formatRaceString(
DB.getValue(nodeChar, "race.baserace"),
DB.getValue(nodeChar, "race.subrace"),
DB.getValue(nodeChar, "race.halfrace"))
Debug.console(race_display)
DB.setValue(nodeChar, "race_string", "string", race_display)
...
The formatting thing (changing it to: if xxx == "" worked and proper string is generated. But...?)
function formatRaceString(race, subrace, halfrace)
Debug.console("formatRaceString", race, subrace, halfrace)
if race == nil then
return ""
end
if subrace == nil then
return race
elseif halfrace == nil then
return subrace
else
return subrace .. " (" .. halfrace .. ")"
end
end
Bonus Question:
Is there an opinion on "Best practices"? If the popup was a modal dialog (something which I will look to see if there is an option in what I open, I seem to recall seeing this before...), I'd simply do the RACE update on "onClose()". I currently do it on the onValueChanged() of any of the 3 race subfields since the user can leave that window open - again, I suspect that is my FIRST problem - picking wrong option there and I will fix it if there is a modal version to use, but still worth asking. Or is it OK to add a "button" to "Apply" changes or "Cancel" as it were and do the caculation/string-concat there?