Ok. I think I have it sorted! It's a very dirty hack for want of a better way to put it. This works for forms which are POSTED. It makes use of the https://forum.evo.im/d/82-formlister-create-multiple-select-options-using-doclister but I've added a little extra to work with checkboxes.
Snippets call is:
[[FormLister?
&formid=`ContactForm`
&debug=`1`
&to=`name@domain.com`
&config=`default:core`
&isHtml=`0`
&protectSubmit=`1`
&rules=`{
"name":{
"required":"Please enter your full name"
},
"email":{
"required":"Please enter your email",
"email":"Please enter a valid email"
},
"phone":{
"required":"Please enter your phone number",
"phone":"Please enter a valid phone number",
"minLength":{
"params":5,
"message":"Please enter a valid phone number"
}
},
"subject":{
"required":"Please enter your subject"
},
"message":{
"required":"Please enter your message",
"minLength":{
"params":100,
"message":"Your message must have at least 100 characters"
}
},
"multiselect":{
"required":"Please choose from the options",
"minCount":{
"params":1,
"message":"At least 1 option is required"
}
}
}`
&formControls=`multiselect`
&arraySplitter=`<br>`
&messagesTpl=`@CODE:<div><ul>[+required+][+errors+][+messages+]</ul></div>`
&messagesOuterTpl=`@CODE:<li>[+messages+]</li>`
&messagesRequiredOuterTpl=`@CODE:<li>[+messages+]</li>`
&messagesErrorOuterTpl=`@CODE:<li>[+messages+]</li>`
&messagesSplitter=`</li><li>`
&messagesRequiredSplitter=`</li><li>`
&messagesErrorSplitter=`</li><li>`
&errorClass=`error`
&requiredClass=`required`
&formControl=`multiselect`
&prepare=`fmMultiSelect,fmCheckBox`
&formTpl=`@CODE:
<script>
jQuery(document).ready(function($){
// Checkbox id prefix
var checkBoxPrefix = 'chk-';
// Load session stored data!
var data = JSON.parse(sessionStorage.getItem("myForm"));
var arrayLength = data.length;
// Work through each element in storage and set checked checkboxes to checked!
for (var i = 0; i < arrayLength; i++) {
var chkName = data[i]['name'];
//Do something
if ( chkName.indexOf(checkBoxPrefix) > -1 )
{
// We need to check the checkboxes!
$('#'+data[i]['name']).prop('checked', true);
}
}
$('#myForm').submit(function (event) {
var data = $('#myForm').serializeArray();
sessionStorage.setItem("myForm", JSON.stringify(data));
//return false;
});
});
</script>
[+form.messages+]
<form action="[~[*id*]~]" method="post" id="myForm">
<input type="hidden" name="formid" value="ContactForm">
<!-- Name -->
<div class="[+name.errorClass+][+name.requiredClass+]">
<label for="name">Name</label>
<input type="text" name="name" id="name" placeholder="Name" value="[+name.value+]">
</div>
<!-- Email -->
<div class="[+email.errorClass+][+email.requiredClass+]">
<label for="email">Email</label>
<input type="email" name="email" id="email" placeholder="Email" value="[+email.value+]">
</div>
<!-- Phone Number -->
<div class="[+phone.errorClass+][+phone.requiredClass+]">
<label for="phone">Phone</label>
<input type="tel" name="phone" id="phone" placeholder="Only Enter Digits" value="[+phone.value+]">
</div>
<!-- Subject -->
<div class="[+subject.errorClass+][+subject.requiredClass+]">
<label for="subject">Subject</label>
<input type="text" name="subject" id="subject" placeholder="Subject" value="[+subject.value+]">
</div>
<!-- Message -->
<div class="[+message.errorClass+][+message.requiredClass+]">
<label for="message">Message</label>
<textarea rows="10" name="message" id="message" placeholder="Type your message here">[+message.value+]</textarea>
</div>
<!-- Multiple Select Options -->
<div class="[+multiselect.errorClass+][+multiselect.requiredClass+]">
<label for="multiselect">Multiple Options</label>
<select name="multiselect[]" id="multiselect" multiple="multiple">
[+options+]
</select>
</div>
<div class="[+checkbox.errorClass+][+checkbox.requiredClass+]">
<label for="checkbox">Check Boxes:</label>
[+checkboxOptions+]
</div>
<!-- Submit Button -->
<button type="submit">Submit</button>
</form>`
&successTpl=`@CODE:<div>Thank you, we will get back to you ASAP.</div>`
&reportTpl=`ContactFormReport`
]]
Notice the new additional code in formTpl?
<script>
jQuery(document).ready(function($){
// Checkbox id prefix
var checkBoxPrefix = 'chk-';
// Load session stored data!
var data = JSON.parse(sessionStorage.getItem("myForm"));
var arrayLength = data.length;
// Work through each element in storage and set checked checkboxes to checked!
for (var i = 0; i < arrayLength; i++) {
var chkName = data[i]['name'];
//Do something
if ( chkName.indexOf(checkBoxPrefix) > -1 ) {
// We need to check the checkboxes!
$('#'+data[i]['name']).prop('checked', true);
}
}
$('#myForm').submit(function (event) {
var data = $('#myForm').serializeArray();
sessionStorage.setItem("myForm", JSON.stringify(data));
//return false;
});
});
</script>
This javascript code does two things.
- Checks the sessionstorage for data. Using that data it will try to check the check boxes accordingly
- On form submit, the form data is save in sessionstorage so the form "state" is saved again
Notice the code is static and uses the Form ID from FormLister formTpl code ("myForm").
** You must ensure you have given your form an ID **
** You must ensure your checkbox prefix matches with your code from the snippet **
In my example the above covers select and checkboxes but we'll concentrate on checkboxes. Notice there are two calls in prepare. fmCheckBox is there to produce the dynamic checkbox content from DocLister
The extra snippet required for checkboxes (fmCheckBox):
<?php
if (!is_array($values)) {
$values = empty($values) ? [] : [$values];
}
$options = $modx->runSnippet('DocLister', [
'parents' => [105],
'orderBy' => 'pagetitle ASC',
'tvList' => 'number',
'renderTV' => 'number',
'addWhereList' => 'hidemenu=1 AND published=1',
'tpl'=>'@CODE:<div class="row"><label><input id="chk-[+id+]" name="chk-[+id+]" type="checkbox" value="[+pagetitle+]" [+selected+] />[+pagetitle+]</label></div>',
'prepare' => function($data) use ($values){
return $data;
}
]);
$FormLister->setPlaceholder('checkboxOptions', $options);
As this is a workaround the following cannot be made use of:
*FormLister rules for the checkboxes.
Hope it works and it makes sense!
BBloke