...
 
Commits (2)
......@@ -685,6 +685,28 @@ export default class FormBase
}
}
for(let option of dompack.qSA(this.node, "select > option"))
{
let formgroup = dompack.closest(option, ".wh-form__fieldgroup");
let visible = !hiddengroups.includes(formgroup) && this._matchesCondition(option.dataset.whFormVisibleIf);
let enabled = visible && enabledgroups.includes(formgroup);
//Record initial states
if (option.propWhFormSavedEnabled === undefined)
option.propWhFormSavedEnabled = !option.disabled;
let option_enabled = enabled && option.propWhFormSavedEnabled;
if(option_enabled !== option.propWhNodeCurrentEnabled)
{
option.propWhNodeCurrentEnabled = option_enabled;
option.disabled = !option_enabled;
if (!isinit && !tovalidate.includes(option.parentNode))
tovalidate.push(option.parentNode); // to clear errors for this option's select field
}
}
if (tovalidate.length)
await this.validate(tovalidate, { focusfailed: false, iffailedbefore: true });
......@@ -742,14 +764,10 @@ export default class FormBase
if (isNodeCollection(matchfield))
{
//Can we set this field? Just take the parent of the first node
if(!this._isNowSettable(matchfield[0]))
return null;
let currentvalue = null;
for (let field of matchfield)
if (field.checked)
if (this._isNowSettable(field) && field.checked)
{
if (field.type != "checkbox")
return field.value;
......
......@@ -778,6 +778,8 @@ PUBLIC STATIC OBJECTTYPE FormRenderingBase
dataset.__extrafields := CellInsert(dataset.__extrafields, field.name, UnmapValueType(ToLowercase(GetTypeName(TypeID(field.value))), field.value, "", FALSE));
}
Print(GetDatasetAsString(dataset));
IF(opt.visiblecondition != "")
Print(` data-wh-form-visible-if="${EncodeValue(opt.visiblecondition)}"`);
Print(`>${opt.htmllabel}</option>`);
}
}
......
......@@ -280,12 +280,12 @@ window.testEqFloat = function(expected, actual, delta, explanation)
function testTrue(actual, explanation)
{
test.eq(true, Boolean(actual), explanation);
testEq(true, Boolean(actual), explanation);
}
function testFalse(actual, explanation)
{
test.eq(false, Boolean(actual), explanation);
testEq(false, Boolean(actual), explanation);
}
......
......@@ -154,6 +154,27 @@ MACRO FillTestFormFile(OBJECT formfile, RECORD options)
, matchtype := "IN"
, value := [1]
]);
OBJECT toggleselectoptions := formpage->AppendComponent("select");
toggleselectoptions->SetAttribute("name", "toggleselectoptions");
toggleselectoptions->SetAttribute("type", "pulldown");
toggleselectoptions->SetAttribute("title", "Toggle options");
FOREVERY(INTEGER suffix FROM [1,2,3])
{
OBJECT toggleselectopt := toggleselectoptions->ownerdocument->CreateElementNS(toggleselectoptions->namespaceuri, "option");
toggleselectopt->SetAttribute("rowkey", "copt" || suffix);
toggleselectopt->SetAttribute("title", "ToggleSelectOpt" || suffix);
toggleselectoptions->AppendChild(toggleselectopt);
IF(options.addconditions AND suffix = 3)
{
formdefs->SetConditionAttribute(toggleselectopt, "visibleconditionid",
[ field := togglesomeoptions->GetAttribute("guid")
, matchtype := "HASVALUE"
, value := FALSE
]);
}
}
}
OBJECT checkboxesfield;
......
import test from '@mod-system/js/wh/testframework';
var urlappend = test.getTestArgument(0)=='replacedcomponents' ? '?dompackpulldown=1' : '';
const replacedcomponents = test.getTestArgument(0)=='replacedcomponents';
const urlappend = replacedcomponents ? '?dompackpulldown=1' : '';
test.registerTests(
[ async function()
......@@ -38,4 +39,63 @@ test.registerTests(
await test.wait('ui');
test.true(JSON.parse(test.qS('#coreformsubmitresponse').textContent).form.agree, "expected successful submit #2");
}
, async function()
{
const alloptions = test.qSA("#coretest-condition_options option");
// 1 and 3 are now checked, so only 2 should be disabled
let disabled_options = test.qSA("#coretest-condition_options option[disabled]").map(_ => _.value);
test.eq(false, disabled_options.includes("1"));
test.eq(true, disabled_options.includes("2"));
test.eq(false, disabled_options.includes("3"));
if (replacedcomponents)
{
test.click(test.qS(".wh-form__fieldgroup[data-wh-form-group-for='condition_options'] .wh-form__pulldown.mypulldown--replaced + .mypulldown .mypulldown__arrow"));
await test.wait('ui');
disabled_options = test.qSA("body > .mypulldown__items .mypulldown__item--disabled").map(_ => alloptions[_.dataset.dompackPulldownIndex].value);
test.eq(false, disabled_options.includes("1"));
test.eq(true, disabled_options.includes("2"));
test.eq(false, disabled_options.includes("3"));
}
// enable 2
test.click('#coretest-checkboxes-2');
disabled_options = test.qSA("#coretest-condition_options option[disabled]").map(_ => _.value);
test.eq(false, disabled_options.includes("1"));
test.eq(false, disabled_options.includes("2"));
test.eq(false, disabled_options.includes("3"));
if (replacedcomponents)
{
test.click(test.qS(".wh-form__fieldgroup[data-wh-form-group-for='condition_options'] .wh-form__pulldown.mypulldown--replaced + .mypulldown .mypulldown__arrow"));
await test.wait('ui');
disabled_options = test.qSA("body > .mypulldown__items .mypulldown__item--disabled").map(_ => alloptions[_.dataset.dompackPulldownIndex].value);
test.eq(false, disabled_options.includes("1"));
test.eq(false, disabled_options.includes("2"));
test.eq(false, disabled_options.includes("3"));
}
// disable 2 and 3
test.click('#coretest-checkboxes-2');
test.click('#coretest-checkboxes-3');
disabled_options = test.qSA("#coretest-condition_options option[disabled]").map(_ => _.value);
test.eq(false, disabled_options.includes("1"));
test.eq(true, disabled_options.includes("2"));
test.eq(true, disabled_options.includes("3"));
if (replacedcomponents)
{
test.click(test.qS(".wh-form__fieldgroup[data-wh-form-group-for='condition_options'] .wh-form__pulldown.mypulldown--replaced + .mypulldown .mypulldown__arrow"));
await test.wait('ui');
disabled_options = test.qSA("body > .mypulldown__items .mypulldown__item--disabled").map(_ => alloptions[_.dataset.dompackPulldownIndex].value);
test.eq(false, disabled_options.includes("1"));
test.eq(true, disabled_options.includes("2"));
test.eq(true, disabled_options.includes("3"));
}
}
]);
......@@ -47,11 +47,13 @@ test.registerTests(
test.fill('select[name="twolevel.customselect.select"]', "abc");
test.false(test.qS('*[data-wh-form-group-for="twolevel.textedit"]').classList.contains("wh-form__fieldgroup--hidden"), "custom textedit should now be visible");
test.false(test.qS('select[name="toggleselectoptions"] option[value="copt3"]').disabled, "ToggleSelectOpt3 should be available");
test.true(test.canClick('input[name="checkboxes"][value="copt3"]'), "CheckBoxOpt3 should be clickable");
test.click('input[name="checkboxes"][value="copt3"]');
test.true(test.canClick('input[name="coptsub3"]'), "CheckBoxOpt3 Subfield should be clickable");
test.click('input[name="togglesomeoptions"]');
test.true(test.qS('select[name="toggleselectoptions"] option[value="copt3"]').disabled, "ToggleSelectOpt3 should no longer be available");
test.false(test.canClick('input[name="checkboxes"][value="copt3"]'), "CheckBoxOpt3 should no longer be clickable");
test.false(test.qS('*[data-wh-form-group-for="extrafield"]').classList.contains("wh-form__fieldgroup--hidden"), "extrafield should not be hidden");
......
......@@ -41,4 +41,5 @@
<test script="testmailconfirmation.whscr"/>
<jstest file="testmailconfirmation-online.es" />
<test script="testformfile-editconditions.whscr"/>
<jstest file="testvisibleconditions.es" />
</group>
import test from '@mod-system/js/wh/testframework';
import * as dompack from 'dompack';
/* More advanced visible conditions */
test.registerTests(
[ async function()
{
await test.load(test.getTestSiteRoot() + 'testpages/formtest/?visibleconditions=1');
// second is only available if first is set
test.false(test.canClick('input[name="second"][value="a_a"]'), "second.a_a not clickable");
test.false(test.canClick('input[name="second"][value="a_b"]'), "second.a_b not clickable");
test.false(test.canClick('input[name="second"][value="b_a"]'), "second.b_a not clickable");
test.false(test.canClick('input[name="second"][value="b_b"]'), "second.b_b not clickable");
// third is only available if second is set
test.false(test.canClick('input[name="third"][value="a"]'), "third.a not clickable");
test.false(test.canClick('input[name="third"][value="b"]'), "third.b not clickable");
// Choosing 'b' for first should enable second's 'b_a' and 'b_b'
test.click('input[name="first"][value="b"]');
test.false(test.canClick('input[name="second"][value="a_a"]'), "second.a_a still not clickable");
test.false(test.canClick('input[name="second"][value="a_b"]'), "second.a_b still not clickable");
test.true(test.canClick('input[name="second"][value="b_a"]'), "second.b_a now clickable");
test.true(test.canClick('input[name="second"][value="b_b"]'), "second.b_b now clickable");
test.false(test.canClick('input[name="third"][value="a"]'), "third.a still not clickable");
test.false(test.canClick('input[name="third"][value="b"]'), "third.b still not clickable");
// Choosing 'b_a' for second should enable third's 'a'
test.click('input[name="second"][value="b_a"]');
test.false(test.canClick('input[name="second"][value="a_a"]'), "second.a_a still not clickable");
test.false(test.canClick('input[name="second"][value="a_b"]'), "second.a_b still not clickable");
test.true(test.canClick('input[name="second"][value="b_a"]'), "second.b_a still clickable");
test.true(test.canClick('input[name="second"][value="b_b"]'), "second.b_b still clickable");
test.true(test.canClick('input[name="third"][value="a"]'), "third.a now clickable");
test.false(test.canClick('input[name="third"][value="b"]'), "third.b still not clickable");
// Switching first to 'a' should enabled second's 'a_a' and 'a_b', but third should no longer be available as none of
// the available second options are chosen, i.e. second is no longer set
test.click('input[name="first"][value="a"]');
test.true(test.canClick('input[name="second"][value="a_a"]'), "second.a_a is now clickable");
test.true(test.canClick('input[name="second"][value="a_b"]'), "second.a_b is now clickable");
test.false(test.canClick('input[name="second"][value="b_a"]'), "second.b_a no longer clickable");
test.false(test.canClick('input[name="second"][value="b_b"]'), "second.b_b no longer clickable");
test.false(test.canClick('input[name="third"][value="a"]'), "third.a no longer clickable");
test.false(test.canClick('input[name="third"][value="b"]'), "third.b still not clickable");
}
]);
......@@ -544,9 +544,9 @@ GetTid("missing.module"); GetTid("system:has.module");`);
TestEq(RECORD[], res.errors);
TestEq([[ line := 7, attrname := "name" ]], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.coretest.radiotest");
TestEq(RECORD[], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.coretest.richtexttid");
TestEq([[ line := 94, attrname := "data-wh-gettid" ]], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.coretest.richtext-tid");
TestEq([[ line := 100, attrname := "data-wh-gettid" ]], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.coretest.richtext-tid");
TestEq(1, Length(SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.multipagetest.nextlabeltid"));
TestEq([[ line := 151, attrname := "pagetid" ]], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.multipagetest.nextpage");
TestEq([[ line := 157, attrname := "pagetid" ]], SELECT line, attrname FROM res.tids WHERE tid="webhare_testsuite:site.multipagetest.nextpage");
res := ValidateSingleFile("mod::webhare_testsuite/moduledefinition.xml");
TestEq(TRUE, RecordExists(SELECT FROM res.tids WHERE tid="webhare_testsuite:module.webruleset"));
......
......@@ -109,4 +109,9 @@ body
{
background:#ddd;
}
&__item--disabled
{
display: none;
}
}
......@@ -84,6 +84,12 @@
<textedit name="condition_not_enabled" title="NOT enabled" />
<textedit name="condition_not_required" title="NOT required" />
<select name="condition_options" title="Conditional options" type="pulldown" rowkeytype="integer">
<option rowkey="1" title="Eins selected" />
<option rowkey="2" tid=".zwei" />
<option rowkey="3" title="Polizei" />
</select>
<wt:matchattributes name="matchattributes_type1" title="type1" attr1="type1" />
<wt:matchattributes name="matchattributes_type2_true" title="type2_true" attr1="type2" attr2="true" />
<wt:matchattributes name="matchattributes_type2_false" title="type2_false" attr1="type2" attr2="false" />
......@@ -321,4 +327,23 @@
</page>
</form>
<form name="visibleconditionsform" objectname="formtest.whlib#VisibleConditionsTestForm" jshandler="anyformhandler">
<page>
<select name="first" title="First choice" type="radio">
<option rowkey="a" title="A" />
<option rowkey="b" title="B" />
</select>
<select name="second" title="Second choice" type="radio">
<option rowkey="a_a" title="A A" />
<option rowkey="a_b" title="A B" />
<option rowkey="b_a" title="B A" />
<option rowkey="b_b" title="B B" />
</select>
<select name="third" title="Third choice" type="radio">
<option rowkey="a" title="A" />
<option rowkey="b" title="B" />
</select>
</page>
</form>
</formdefinitions>
......@@ -84,6 +84,12 @@ PUBLIC STATIC OBJECTTYPE FormTestPage EXTEND WebPageBase
, [ anyform := this->webdesign->GetWittyDataForForm("datetimeform")
]);
}
ELSE IF(GetWebVariable("visibleconditions")="1")
{
RETURN PTR EmbedWittyComponent(Resolve("formtest.witty:anyform")
, [ anyform := this->webdesign->GetWittyDataForForm("visibleconditionsform")
]);
}
ELSE
{
RETURN PTR EmbedWittyComponent(Resolve("formtest.witty:forms")
......@@ -271,34 +277,28 @@ PUBLIC STATIC OBJECTTYPE CoreTestForm EXTEND FormBase
// Countrylist is already set by XML and cannot be updated
TestThrows(PTR MemberUpdate(^address, 'countrylist', [ "NL" ]));
^checkboxes->visiblecondition := FCIsSet(^checkboxesvisible);
^condition_or_visible->visiblecondition :=
[ matchtype := "OR"
, conditions :=
[ [ matchtype := "HASVALUE", field := "condition_or_1", value := TRUE ]
, [ matchtype := "HASVALUE", field := "condition_or_2", value := TRUE ]
]
];
^condition_and_visible->visiblecondition :=
[ matchtype := "AND"
, conditions :=
[ [ matchtype := "HASVALUE", field := "condition_and_1", value := TRUE ]
, [ matchtype := "HASVALUE", field := "condition_and_2", value := TRUE ]
]
];
^condition_not_enabled->enabledcondition :=
[ matchtype := "NOT"
, condition := [ matchtype := "HASVALUE", field := "condition_not", value := FALSE ]
];
^condition_not_required->requiredcondition :=
[ matchtype := "NOT"
, condition := [ matchtype := "HASVALUE", field := "condition_not", value := FALSE ]
];
^condition_or_visible->visiblecondition := FCOr(
[ FCIsSet(^condition_or_1)
, FCIsSet(^condition_or_2)
]);
^condition_and_visible->visiblecondition := FCAnd(
[ FCIsSet(^condition_and_1)
, FCIsSet(^condition_and_2)
]);
^condition_not_enabled->enabledcondition := FCNot(FCNot(FCIsSet(^condition_not)));
^condition_not_required->requiredcondition := FCIsSet(^condition_not);
// Don't make the field conditionally required on the HTML only page
^condition_not_enabled->required := TRUE;
// Link requiredradio's "Y" option to our checkbox
^requiredradio->options[1].visiblecondition := FCIsset(^showradioy);
^requiredradio->options[1].visiblecondition := FCIsSet(^showradioy);
// Conditional select options
^condition_options->options :=
SELECT *
, visiblecondition := FCMatch(^checkboxes, "HAS", INTEGER[ rowkey ])
FROM ^condition_options->options;
IF(nocheckboxselect)
^checkboxes->value := INTEGER[];
......@@ -818,3 +818,20 @@ PUBLIC STATIC OBJECTTYPE DateTimeTestForm EXTEND FormBase
];
}
>;
PUBLIC STATIC OBJECTTYPE VisibleConditionsTestForm EXTEND FormBase
<
MACRO NEW()
{
^second->visiblecondition := FCIsSet(^first);
^second->options :=
SELECT *
, visiblecondition := FCMatch(^first, "IN", [ Left(rowkey, 1) ])
FROM ^second->options;
^third->visiblecondition := FCIsSet(^second);
^third->options :=
SELECT *
, visiblecondition := FCMatch(^second, "IN", SELECT AS STRING ARRAY second.rowkey FROM ^second->options AS second WHERE second.rowkey LIKE "*" || third.rowkey)
FROM ^third->options AS third;
}
>;
......@@ -4529,9 +4529,9 @@
}
},
"dompack": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/dompack/-/dompack-1.9.0.tgz",
"integrity": "sha512-A7zYIS3Nk3QQbzuj1KgaQyjm+xAVXJeD5+mbpYnxOLFbtXoDDGy4znX6jbMoZxWiuLX+fx92+zqNVJwr1QcEhA=="
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/dompack/-/dompack-1.9.1.tgz",
"integrity": "sha512-suzFb7F1d9zOl1dZ/EYeeOY8ZnUHgiu46sKzu5+HlbCmAwRyZhdCtsTuWtk4urzHpbz8diSb3cWmSLjhnwEvmA=="
},
"domutils": {
"version": "1.7.0",
......
......@@ -5,7 +5,7 @@
"@webhare/dompack-builder": "^1.6.0",
"babel-eslint": "^10.0.1",
"diff": "^4.0.1",
"dompack": "^1.9.0",
"dompack": "^1.9.1",
"eslint": "^5.16.0",
"eslint-plugin-import": "^2.17.2",
"eslint-plugin-react": "^7.13.0",
......