diff --git a/README.md b/README.md index 3094801d4..02688efc4 100644 --- a/README.md +++ b/README.md @@ -1263,6 +1263,39 @@ Honeycrisp contains JavaScript logic that deselects the other checkboxes when "N selected. To enable it, you'll need to add `noneOfTheAbove.init()` to your JavaScript that runs after page load. +The `content` parameter provides flexibility for the checkboxes list in the checkbox set and might be a better option +for dynamic values (like household member names). + +The `options` parameter provides some convenience for static checkbox sets. A collection of objects that +implement `InputOption` can be passed into `checkboxFieldset`. + +```java +enum ProgramOption implements InputOption { + SNAP("programs.SNAP", "programs-desc.SNAP"), + CCAP("programs.CCAP", "programs-desc.CCAP"), + GRH("programs.GRH", "programs-desc.GRH"), + CASH("programs.CASH", "programs-desc.CASH"), + OTHER("programs.Other", null); + + // Should be defined by their message properties + final String label; + final String helpText; + + // ... constructor and getters +} +``` + +```html + + +``` + ##### Checkbox ```html @@ -1336,6 +1369,34 @@ The `radioFieldset` has an optional `radioHelpText` field which will appear unde fieldset's legend. `radio`, too, has an optional `radioHelpText` field which will appear under the label's description text. +This fragment also supports passing a collection of `options` instead of using `content`. +The `options` parameter provides some convenience for static radio sets. A collection of objects that +implement `InputOption` can be passed into `radioFieldset`. + +```java +enum ColorOption implements InputOption { + BLUE("color.blue", "color-desc.blue"), + RED("color.red", "color-desc.red"), + YELLOW("color.yellow", null); + + // Should be defined by their message properties + final String label; + final String helpText; + + // ... constructor and getters +} +``` + +```html + + +``` + For convenience, we have provided a `cfa:inputFieldsetWithRadio` live template which can be used to quickly create groupings of radio inputs. Not that when using this template, you can copy the inner radio option fragment as many times as you like to create the necessary number of radio options. @@ -2160,7 +2221,7 @@ public class ApplicantDateOfBirthPreparer implements SubmissionFieldPreparer { @Override public Map prepareSubmissionFields(Submission submission, - PdfMap pdfMap) { + PdfMap pdfMap) { Map submissionFields = new HashMap<>(); String month = submission.getInputData().get("applicantBirthMonth").toString(); @@ -2211,7 +2272,7 @@ public class DataBaseFieldPreparer implements SubmissionFieldPreparer { @Override public Map prepareSubmissionFields(Submission submission, - PdfMap pdfMap) { + PdfMap pdfMap) { Map submissionFields = new HashMap<>(); ArrayList> houseHoldSubflow = (ArrayList>) submission.getInputData() @@ -2422,7 +2483,7 @@ Below is an example of a sendEmail() call being made by an application using the Please note that pdfs is a list of files to be passed as attachments with the email. ```java -MessageResponse response = mailgunEmailClient.sendEmail( +MessageResponse response=mailgunEmailClient.sendEmail( emailSubject, recipientEmail, emailToCc, @@ -2430,7 +2491,7 @@ MessageResponse response = mailgunEmailClient.sendEmail( emailBody, pdfs, requireTls -); + ); ``` The `sendEmail()` method will send an email and return the `MessageResponse` object it receives from diff --git a/src/main/java/formflow/library/inputs/InputOption.java b/src/main/java/formflow/library/inputs/InputOption.java new file mode 100644 index 000000000..5bb19f250 --- /dev/null +++ b/src/main/java/formflow/library/inputs/InputOption.java @@ -0,0 +1,10 @@ +package formflow.library.inputs; + +public interface InputOption { + String getValue(); + + String getLabel(); + + String getHelpText(); + +} diff --git a/src/main/resources/templates/fragments/inputs/checkboxFieldset.html b/src/main/resources/templates/fragments/inputs/checkboxFieldset.html index 64a2dfea7..ddd56bb6b 100644 --- a/src/main/resources/templates/fragments/inputs/checkboxFieldset.html +++ b/src/main/resources/templates/fragments/inputs/checkboxFieldset.html @@ -4,6 +4,9 @@ hasHelpText=${!#strings.isEmpty(fieldsetHelpText)}, hasLabel=${!#strings.isEmpty(label)}, hasAriaLabel=${!#strings.isEmpty(ariaLabel)}, + hasOptions=${options != null}, + hasContent=${!hasOptions}, + hasNoneOfTheAboveOption=${!#strings.isEmpty(noneOfTheAboveLabel)}, hasError=${ errorMessages != null && errorMessages.get(inputName) != null && @@ -11,7 +14,7 @@ th:assert=" ${!#strings.isEmpty(inputName)}, ${hasLabel || hasAriaLabel}, - ${content != null}"> + ${hasContent || hasOptions}">

- + + + + + + + + + + +
diff --git a/src/main/resources/templates/fragments/inputs/radioFieldset.html b/src/main/resources/templates/fragments/inputs/radioFieldset.html index 585708da7..c19d35166 100644 --- a/src/main/resources/templates/fragments/inputs/radioFieldset.html +++ b/src/main/resources/templates/fragments/inputs/radioFieldset.html @@ -4,6 +4,8 @@ hasHelpText=${!#strings.isEmpty(fieldsetHelpText)}, hasLabel=${!#strings.isEmpty(label)}, hasAriaLabel=${!#strings.isEmpty(ariaLabel)}, + hasOptions=${options != null}, + hasContent=${!hasOptions}, hasError=${ errorMessages != null && errorMessages.get(inputName) != null && @@ -11,7 +13,7 @@ th:assert=" ${!#strings.isEmpty(inputName)}, ${hasLabel || hasAriaLabel}, - ${content != null}"> + ${hasContent || hasOptions}">

- + + + + + + + +
diff --git a/src/test/java/formflow/library/framework/InputsTest.java b/src/test/java/formflow/library/framework/InputsTest.java index be229e079..584e510d6 100644 --- a/src/test/java/formflow/library/framework/InputsTest.java +++ b/src/test/java/formflow/library/framework/InputsTest.java @@ -6,6 +6,7 @@ import formflow.library.address_validation.AddressValidationService; import formflow.library.address_validation.ValidatedAddress; +import formflow.library.inputs.TestOption; import formflow.library.utilities.AbstractMockMvcTest; import formflow.library.utilities.FormScreen; import java.util.HashMap; @@ -39,8 +40,10 @@ void shouldPersistInputValuesWhenNavigatingBetweenScreens() throws Exception { String numberInput = "123"; // First "" value is from hidden input that a screen would submit List checkboxSet = List.of("", "Checkbox-A", "Checkbox-B"); + List checkboxEnumSet = List.of("MANGO", "OTHER"); List checkboxInput = List.of("", "checkbox-value"); String radioInput = "Radio B"; + String radioInputEnum = TestOption.MANGO.getValue(); String selectInput = "Select B"; String moneyInput = "100"; String phoneInput = "(555) 555-1234"; @@ -57,9 +60,11 @@ void shouldPersistInputValuesWhenNavigatingBetweenScreens() throws Exception { Map.entry("numberInput", List.of(numberInput)), // CheckboxSet's need to have the [] in their name for POST actions Map.entry("checkboxSet[]", checkboxSet), + Map.entry("checkboxEnumSet[]", checkboxEnumSet), // Checkboxes need to have the [] in their name for POST actions Map.entry("checkboxInput[]", checkboxInput), Map.entry("radioInput", List.of(radioInput)), + Map.entry("radioInputEnum", List.of(radioInputEnum)), Map.entry("selectInput", List.of(selectInput)), Map.entry("moneyInput", List.of(moneyInput)), Map.entry("phoneInput", List.of(phoneInput)), @@ -81,8 +86,10 @@ void shouldPersistInputValuesWhenNavigatingBetweenScreens() throws Exception { assertThat(inputsScreen.getInputValue("dateYear")).isEqualTo(dateYear); assertThat(inputsScreen.getInputValue("numberInput")).isEqualTo(numberInput); assertThat(inputsScreen.getCheckboxSetValues("checkboxSet")).isEqualTo(removedHiddenCheckboxSet); + assertThat(inputsScreen.getCheckboxSetValues("checkboxEnumSet")).isEqualTo(checkboxEnumSet); assertThat(inputsScreen.getCheckboxSetValues("checkboxInput")).isEqualTo(removedHiddenCheckboxInput); assertThat(inputsScreen.getRadioValue("radioInput")).isEqualTo(radioInput); + assertThat(inputsScreen.getRadioValue("radioInputEnum")).isEqualTo(radioInputEnum); assertThat(inputsScreen.getSelectValue("selectInput")).isEqualTo(selectInput); assertThat(inputsScreen.getInputValue("moneyInput")).isEqualTo(moneyInput); assertThat(inputsScreen.getInputValue("phoneInput")).isEqualTo(phoneInput); diff --git a/src/test/java/formflow/library/inputs/TestFlow.java b/src/test/java/formflow/library/inputs/TestFlow.java index 486c8015e..b5bb6ab76 100644 --- a/src/test/java/formflow/library/inputs/TestFlow.java +++ b/src/test/java/formflow/library/inputs/TestFlow.java @@ -36,8 +36,10 @@ public class TestFlow extends FlowInputs { String numberInput; ArrayList checkboxSet; + ArrayList checkboxEnumSet; ArrayList checkboxInput; String radioInput; + String radioInputEnum; String selectInput; String moneyInput; String phoneInput; diff --git a/src/test/java/formflow/library/inputs/TestOption.java b/src/test/java/formflow/library/inputs/TestOption.java new file mode 100644 index 000000000..6019793d3 --- /dev/null +++ b/src/test/java/formflow/library/inputs/TestOption.java @@ -0,0 +1,30 @@ +package formflow.library.inputs; + +public enum TestOption implements InputOption { + MANGO("input-options.fruit.mango", "input-options.fruit.mango-desc"), + PAPAYA("input-options.fruit.papaya", "input-options.fruit.papaya-desc"), + GUAVA("input-options.fruit.guava", null), + OTHER("general.other", null); + + public String getLabel() { + return label; + } + + private final String label; + + public String getHelpText() { + return helpText; + } + + private final String helpText; + + TestOption(String label, String helpText) { + this.label = label; + this.helpText = helpText; + } + + @Override + public String getValue() { + return this.name(); + } +} diff --git a/src/test/resources/templates/testFlow/inputs.html b/src/test/resources/templates/testFlow/inputs.html index 5c0d25a9a..62c2237dd 100644 --- a/src/test/resources/templates/testFlow/inputs.html +++ b/src/test/resources/templates/testFlow/inputs.html @@ -38,6 +38,13 @@ th:replace="~{fragments/inputs/checkboxInSet :: checkboxInSet(inputName='checkboxSet', value='Checkbox-B', label='Checkbox B')}"/> + + + + + + + +