Skip to content

Commit

Permalink
[PBNTR-361] Implementing Dropdown form validation (#3507)
Browse files Browse the repository at this point in the history
**What does this PR do?**
Implementing form validation for required Dropdown.

**Screenshots:** 
<img width="761" alt="image"
src="https://github.com/powerhome/playbook/assets/2573205/5265299d-a1fa-449b-928c-1e0c64eb2637">

**How to test?** 
1. Go to the Form kit doc
2. Scroll down to Validation doc


#### Checklist:
- [x] **LABELS** Add a label: `enhancement`, `bug`, `improvement`, `new
kit`, `deprecated`, or `breaking`. See [Changelog &
Labels](https://github.com/powerhome/playbook/wiki/Changelog-&-Labels)
for details.
- [x] **DEPLOY** I have added the `milano` label to show I'm ready for a
review.
- [ ] **TESTS** I have added test coverage to my code.
  • Loading branch information
carloslimasd committed Jul 5, 2024
1 parent 52b5c19 commit 19734b1
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 5 deletions.
4 changes: 3 additions & 1 deletion playbook/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
<%= pb_rails("caption", props: {text: object.label, margin_bottom:"xs"}) %>
<% end %>
<div class="dropdown_wrapper<%= error_class %>" style="position: relative">
<input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value=""/>
<input type="hidden" name="<%= object.name %>" id="dropdown-selected-option" value="" />
<input id="dropdown-form-validation" name="<%= object.name %>_form_validation" value="" style="display: none" <%= object.required ? "required" : ""%> />

<% if content.present? %>
<%= content.presence %>
<%= pb_rails("body", props: { status: "negative", text: object.error }) %>
Expand Down
2 changes: 2 additions & 0 deletions playbook/app/pb_kits/playbook/pb_dropdown/dropdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class Dropdown < Playbook::KitBase
prop :label, type: Playbook::Props::String
prop :name, type: Playbook::Props::String
prop :error, type: Playbook::Props::String
prop :required, type: Playbook::Props::Boolean,
default: false

def data
Hash(prop(:data)).merge(pb_dropdown: true)
Expand Down
37 changes: 33 additions & 4 deletions playbook/app/pb_kits/playbook/pb_dropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ const DOWN_ARROW_SELECTOR = "#dropdown_open_icon";
const UP_ARROW_SELECTOR = "#dropdown_close_icon";
const OPTION_SELECTOR = "[data-dropdown-option-label]";
const CUSTOM_DISPLAY_SELECTOR = "[data-dropdown-custom-trigger]";
const INPUT_FORM_VALIDATION = "#dropdown-form-validation";

export default class PbDropdown extends PbEnhancedElement {
static get selector() {
return DROPDOWN_SELECTOR;
}

get target() {
return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
}

connect() {
this.keyboardHandler = new PbDropdownKeyboard(this);
this.bindEventListeners();
this.updateArrowDisplay(false);
this.handleFormValidation();
}

bindEventListeners() {
Expand All @@ -38,9 +44,13 @@ export default class PbDropdown extends PbEnhancedElement {
handleOptionClick(event) {
const option = event.target.closest(OPTION_SELECTOR);
const hiddenInput = this.element.querySelector("#dropdown-selected-option");
const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);

if (option) {
const value = option.dataset.dropdownOptionLabel;
hiddenInput.value = JSON.parse(value).id;
inputFormValidation.value = JSON.parse(value).id;
this.clearFormValidation(inputFormValidation);
this.onOptionSelected(value, option);
}
}
Expand Down Expand Up @@ -103,10 +113,6 @@ export default class PbDropdown extends PbEnhancedElement {
selectedOption.classList.add("pb_dropdown_option_selected");
}

get target() {
return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
}

showElement(elem) {
elem.classList.remove("close");
elem.classList.add("open");
Expand Down Expand Up @@ -150,4 +156,27 @@ export default class PbDropdown extends PbEnhancedElement {
upArrow.style.display = isOpen ? "inline-block" : "none";
}
}

handleFormValidation() {
const inputFormValidation = this.element.querySelector(INPUT_FORM_VALIDATION);

inputFormValidation.addEventListener("invalid", function (event) {
if (inputFormValidation.hasAttribute("required") && inputFormValidation.value === "") {
event.preventDefault();
inputFormValidation.closest(".dropdown_wrapper").classList.add("error");
}
}, true);
}

clearFormValidation(input) {
if (input.checkValidity()) {
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
dropdownWrapperElement.classList.remove("error");

const errorLabelElement = dropdownWrapperElement.querySelector(".pb_body_kit_negative");
if (errorLabelElement) {
errorLabelElement.remove();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
]
%>
<%
example_dropdown_options = [
{ label: 'United States', value: 'United States', id: 'us' },
{ label: 'Canada', value: 'Canada', id: 'ca' },
{ label: 'Pakistan', value: 'Pakistan', id: 'pk' },
]
%>
<%= pb_form_with(scope: :example, method: :get, url: "", validate: true) do |form| %>
<%= form.text_field :example_text_field, props: { label: true, required: true } %>
<%= form.phone_number_field :example_phone_number_field, props: { label: "Example phone field" } %>
Expand All @@ -22,6 +30,7 @@
<%= form.password_field :example_password_field, props: { label: true, required: true } %>
<%= form.url_field :example_url_field, props: { label: true, required: true } %>
<%= form.text_area :example_text_area, props: { label: true, required: true } %>
<%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options, required: true } %>
<%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true } %>
<%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
<%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
Expand Down

0 comments on commit 19734b1

Please sign in to comment.