Just wanted to bump this and see if any of my heroes from the past have an idea. Hi @MegaJerk, @nico, @TomaszPoszytek, @cassymfreeman, @SimonMuntz, @mlauer! Do any of you have an idea on this or a resource you might point me to?
Thanks and Best Regards,
Patrick
The problem that I see a lot of people have with coding logic is that they don't understand how things are evaluated and it creates confusion because we tend to think of things broadly as humans, but need to think of things incredibly specifically in terms of how we plot out all of the contingencies for how we're expecting to interpret any particular state (that we need to define using logical operators).
Take, for instance, the logical or (aka: ||)
It will return true as soon as one of the expressions being evaluated equals true. This means that if you have written something like:
cho_AbsenceType!="Sick" || somethingElse;
That means that somethingElse will NEVER be evaluated so long as cho_AbsenceType does NOT equal "Sick", because as long as it doesn't that side of the or statement is true.
Logically that also means that somethingElse will only be evaluated when cho_AbsenceType DOES equal "Sick".
However, in this case there is also extra confusion because the two different sets of code you present above are not at all equal.
To easily prove this / test this, I have setup two little Calculated Controls, one with a formula using the Nintex Runtime Functions, and another using the JS Logical Operators:
Immediately upon loading everything seems correct:
cho_AbsenceType !="Sick" which is true for both.
What happens if we change it to "Leave":
This also seems correct because:
cho_AbsenceType == "Leave"
AND
cho_AddSickToLeave!="Yes"
However, let's check the box and see what happens:
Hmm... Uh oh.
Well what happens if we select a completely different option?
Well now we're getting divergent results!!!
So what's going on? Well... sort of two things. On the Javascript side, our second test using the "Leave" as the value and the Yes/No uncheck is actually incorrect! Because we didn't select "Sick" that part of the or statement actually returned true immediately and so it only appeared correct. That's why when we checked the box, it remained true even though on the right side of your or statement, that would be a "false".
Additionally (and more apparent in the later tests) our logic starts to diverge between the JS and the Runtime Function version because the Runtime Functions are not being correctly used.
Here is the actual JavaScript that those Runtime Functions use:
NWF.RuntimeFunctions.equals = function (value1, value2) {
return value1 === value2;
};
NWF.RuntimeFunctions.and = function (bool1, bool2) {
return bool1 && bool2;
};
NWF.RuntimeFunctions.or = function (bool1, bool2) {
return bool1 || bool2;
};
NWF.RuntimeFunctions.not = function (bool) {
return !bool;
};
The way you have written the 'not' statement is actually incorrect:
not(cho_AbsenceType,"Sick")
because you're skipping the "equals" step.
However, how this ends up being interpreted in code is that when cho_AbsenceType doesn't have a value (or is an empty string), it's considered false, and therefore returns true after being ran through that function! Likewise, when it *has* a value (when the string isn't empty), that's considered "truthy" and the not function returns a false which then leads us to the second half of the Or statement:
and(equals(cho_AbsenceType,"Leave"), not(equals(cho_AddSickToLeave,"Yes")))
or
((cho_AbsenceType == "Leave") && (cho_AddSickToLeave!="Yes")))
These are more correct but also wrong. The biggest problem is that Yes/No controls do not return "Yes" or "No", actually (though you can in some cases evaluate against the values they return as if they do depending on the context (like a workflow!)). What it really returns is a boolean value of true or false.
This means that BOTH code gets it wrong by asking:
cho_AddSickToLeave!="Yes"
// or
not(equals(cho_AddSickToLeave, "Yes"))
ALL THAT ASIDE!
My general thought behind making solid logic is to just try to figure out where the fewest "true things" are. This means that if you really wanna ONLY show your form when:
- cho_AbsenseType = "Sick"
- cho_AbsenseType = "Leave" AND cho_AddSickToLeave = "Yes" (or true;))
then target those few conditions and then INVERSE the result like:
!(cho_AbsenceType === "Sick" || cho_AbsenceType === "Leave" && cho_AddSickToLeave)
I also enjoy this method because it typically also more correctly describes it "how" we're thinking about it.
Looking at the form now we have on start (and paying attention really to the JS Formula):
The Panel would be in this case "hidden" because it's returning true
When we select Sick:
The Panel would Show
When we select Leave:
The Panel would Hide
But then add Sick to it:
The Panel would Show
And if we select something entirely different then it will once again hide:
--------
I hope that this helps to shine some light onto things and doesn't just muddy the waters. It's 5am so I don't really know how reliably I am explaining things, but if you need further assistance or more explanation for things or how I broke this down, let me know.
Another amazing response! thanks you sir.
Kindest Regards,
Patrick