Implements the filter options feature

This commit is contained in:
Jean-Baptiste Bellet
2022-09-27 14:55:20 +02:00
parent 0f9ebfe34a
commit 23e2d28488
4 changed files with 49 additions and 3 deletions

View File

@@ -1,8 +1,9 @@
# frozen_string_literal: true
class MultipleCheckedSelectComponent < ViewComponent::Base
def initialize(name:, options:, selected:)
def initialize(name:, options:, selected:, filter_placeholder: "Filter options")
@name = name
@filter_placeholder = filter_placeholder
@options = options
@selected = selected.map(&:to_sym)
end

View File

@@ -4,9 +4,12 @@
= "&nbsp; #{t('admin.columns')}".html_safe
%span{ class: "icon-caret-down", "data-multiple-checked-select-target": "caret" }
%div.menu{ class: "hidden", "data-multiple-checked-select-target": "options" }
%div.filter
%input{ type: "text", "data-multiple-checked-select-target": "filter", placeholder: @filter_placeholder }
%hr
- @options.each do |option|
- classes = @selected.include?(option[1]) ? "selected" : ""
%div.menu_item{ class: classes, "data-multiple-checked-select-target": "option", "data-value": option[1] }
%div.menu_item{ class: classes, "data-multiple-checked-select-target": "option", "data-value": option[1], "data-label": option[0] }
%span.check
%span.name{id: option[1]}
= option[0]

View File

@@ -1,7 +1,7 @@
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["button", "caret", "options", "option", "inputs"];
static targets = ["button", "caret", "options", "option", "inputs", "filter"];
static values = { inputName: String };
connect() {
@@ -13,12 +13,26 @@ export default class extends Controller {
});
this.buildInputs();
document.addEventListener("click", this.closeOptions);
this.filterTarget.addEventListener("input", this.filterOptions);
}
disconnect() {
document.removeEventListener("click", this.closeOptions);
}
// private methods
filterOptions = (e) => {
const filter = e.target.value.toLowerCase();
this.optionTargets.forEach((option) => {
if (option.dataset["label"].toLowerCase().includes(filter)) {
option.classList.remove("hidden");
} else {
option.classList.add("hidden");
}
});
};
toggleOptions = () => {
this.optionsTarget.classList.toggle("hidden");
this.caretTarget.classList.toggle("icon-caret-down");

View File

@@ -99,6 +99,30 @@
z-index: 100;
white-space: nowrap;
.filter {
padding-left: 5px;
padding-right: 5px;
position: relative;
> input[type="text"] {
border: 1px solid rgba(18, 18, 18, 0.1);
width: 100%;
padding-left: 30px;
padding-top: 10px;
padding-bottom: 10px;
font-size: 13px;
color:#454545;
}
&:after {
content: "\f002";
font-family: FontAwesome;
position: absolute;
left: 15px;
top: 13px;
color:#454545;
}
}
.menu_item {
margin: 0px;
@@ -126,6 +150,10 @@
content: "\2713";
}
}
&.hidden {
display: none;
}
}
.menu_item:hover {