Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: update select component #310

Merged
merged 7 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.css.scss.erb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
@import "register";
@import "lostpassword";
@import "flatpickr/dist/themes/light";
@import "tom-select/dist/scss/tom-select";
@import "feedback";
@import "login";
@import "components/index";
Expand Down
49 changes: 44 additions & 5 deletions app/assets/stylesheets/components/input_field.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.input-field-component{
.input-field-component {
width: 100%;
font-size: 13px;
padding: 10px;
Expand All @@ -8,23 +8,62 @@
resize: none;
}

.input-field-component:focus{
.input-field-component:focus {
border: 1px solid var(--primary-color);
}

.text-input-label{
.text-input-label {
font-size: 12px;
color: #666666;
margin-bottom: 5px;
}

.text-input-error-text{
.text-input-error-text {
font-size: 12px;
color: var(--error-color)
}

.text-input-helper-text{
.text-input-helper-text {
font-size: 12px;
color: #666666;
margin-top: 5px;
}

.ts-control {
padding: 12px;
border-radius: 5px;
border-color: #BDBDBD;
}

.ts-dropdown-content .option {
padding: 12px;
}

.ts-dropdown .active {
background-color: #f8f8f8;

}

.ts-dropdown {
margin: 0;
color: #666666;
}

.chosen-container {
padding: 0;
border-radius: 5px;
}

.ts-wrapper.single .ts-control:after {
border-color: #343a40 transparent transparent;
border-style: solid;
border-width: 5px 5px 0;
content: " ";
display: block;
height: 0;
margin-top: -3px;
position: absolute;
right: calc(0.75rem + 5px);
top: 50%;
width: 0;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
%div{:data => { controller: "select-input", 'select-input': {'multiple-value': @multiple.to_s}}}
= select_tag(@name, options_values, { multiple: @multiple, class: "form-control", id: "select_#{@id}", data: { action: "select-input#toggleOtherValue", "select-input-target": "selectedValues" } })

%div.d-flex.mt-1{style: "display:#{!@open_to_add_values ? 'none !important;' : 'block;'}"}
= text_field_tag("add_#{@id}", nil, :style => "margin-right: 1em;width: 16em;display: none;", :placeholder => "Or provide the value",
data: {action: "keydown.enter->select-input#addValue", "select-input-target": "inputValueField"}, class: 'metadataInput form-control form-control-sm')

%button.btn.btn-primary.btn-sm.add-value-btn{id: "btnAdd#{@id}", style: "display: none;",
data: { action: "select-input#addValue", "select-input-target": "btnValueField"}}
Add new value
%select{id: "select_#{@id}", autocomplete:"off", multiple: @multiple ,data: {controller: "select-input", 'select-input':{'multiple-value':@multiple, 'open-add-value':@open_to_add_values}}}
- @values.each do |value|
%option{value:@value, selected: value.eql?(@selected)}
= value

Original file line number Diff line number Diff line change
@@ -1,137 +1,16 @@
import {Controller} from "@hotwired/stimulus"
import {useChosen} from "../../javascript/mixins/useChosen";
import { Controller } from "@hotwired/stimulus"
import TomSelect from "tom-select"

export default class extends Controller {

static values = {
other: {type: Boolean, default: true},
multiple: {type: Boolean, default: false}
}

static targets = ["btnValueField", "inputValueField", "selectedValues"]

connect() {
this.initMultipleSelect()
this.#displayOtherValueField()
}

toggleOtherValue() {
if (this.otherValue && !this.multipleValue) {
this.#toggle()
let myOptions = {}
if (this.data.get("multipleValue")) {
myOptions['plugins'] = ['remove_button'];
}
}

addValue(event) {
event.preventDefault()

if (this.inputValueFieldTarget.value) {
let newOption = this.inputValueFieldTarget.value;
this.#addNewOption(newOption)
this.#selectNewOption(newOption)
if (!this.multipleValue) {
this.#hideOtherValueField()
}
if (this.data.get("openAddValue")) {
myOptions['create'] = true;
}
new TomSelect(this.element, myOptions);
}


initMultipleSelect() {
this.#addEmptyOption()
useChosen(this.selectedValuesTarget, {
width: '100%',
search_contains: true,
allow_single_deselect: !this.multipleValue,
}, (event) => {
if(this.multipleValue){
let selected = event.target.selectedOptions
if (selected.length === 0) {
this.#selectEmptyOption()
} else {
this.#unSelectEmptyOption()
}
}
})
}

#selectEmptyOption() {
this.emptyOption.selected = true
this.emptyOption.disabled = false
}

#unSelectEmptyOption() {
this.emptyOption.selected = false
this.emptyOption.disabled = true
}

#addEmptyOption() {
this.emptyOption = document.createElement("option")
this.emptyOption.innerHTML = ''
this.emptyOption.value = ''
this.selectedValuesTarget.prepend(this.emptyOption)
}

#selectNewOption(newOption) {
let selectedOptions = this.#selectedOptions();


if (Array.isArray(selectedOptions)) {
selectedOptions.push(newOption);
} else {
selectedOptions = [];
selectedOptions.push(newOption)
}

this.selectedValuesTarget.value = selectedOptions
if (this.multipleValue) {
const options = this.selectedValuesTarget.options
for (const element of options) {
element.selected = selectedOptions.indexOf(element.value) >= 0;
}
jQuery(this.selectedValuesTarget).trigger("chosen:updated")
}

}

#addNewOption(newOption) {
let option = document.createElement("option");
option.value = newOption;
option.text = newOption;
this.selectedValuesTarget.add(option)
}

#selectedOptions() {
if (this.multipleValue) {
const selectedOptions = [];
for (let option of this.selectedValuesTarget.options) {
if (option.selected) {
selectedOptions.push(option.value);
}
}
return selectedOptions
} else {
return this.selectedValuesTarget.value
}
}

#toggle() {
if (this.selectedValuesTarget.value === 'other') {
this.#displayOtherValueField()
} else {
this.#hideOtherValueField()
}
}

#displayOtherValueField() {
this.inputValueFieldTarget.value = ""
this.btnValueFieldTarget.style.display = 'block'
this.inputValueFieldTarget.style.display = 'block'
}

#hideOtherValueField() {
this.inputValueFieldTarget.value = ""
this.btnValueFieldTarget.style.display = 'none'
this.inputValueFieldTarget.style.display = 'none'
}


}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"split.js": "^1.6.5",
"stimulus-flatpickr": "^3.0.0-0",
"stimulus-rails-nested-form": "^4.0.0",
"stimulus-read-more": "^4.1.0"
"stimulus-read-more": "^4.1.0",
"tom-select": "^2.2.2"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds"
Expand Down
2 changes: 2 additions & 0 deletions test/components/previews/input/select_component_preview.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class Input::SelectComponentPreview < ViewComponent::Preview
layout 'component_preview_not_centred'

def default(id: "", name: "", values: ["choices 1", "choices 2", "choices 3"], selected: "choices 2", multiple: false, open_to_add_values: false)
render Input::SelectComponent.new(id: id, name: name, value: values, selected: selected, multiple: multiple, open_to_add_values: open_to_add_values)
end
Expand Down
20 changes: 20 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.2.4.tgz#0d35541be32cfae3b4f78c6ab9138f5b21f28a21"
integrity sha512-c3xlOroHp/cCZHDOuLp6uzQYEbvXBUVaal0puXoGJ9M8L/KHwZ3hQozD4dVeSN9msHWLxxtmPT1TlCN7gFhj4w==

"@orchidjs/sifter@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@orchidjs/sifter/-/sifter-1.0.3.tgz#43f42519472282eb632d0a1589184f044d64129b"
integrity sha512-zCZbwKegHytfsPm8Amcfh7v/4vHqTAaOu6xFswBYcn8nznBOuseu6COB2ON7ez0tFV0mKL0nRNnCiZZA+lU9/g==
dependencies:
"@orchidjs/unicode-variants" "^1.0.4"

"@orchidjs/unicode-variants@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@orchidjs/unicode-variants/-/unicode-variants-1.0.4.tgz#6d2f812e3b19545bba2d81caffff1204de9a6a58"
integrity sha512-NvVBRnZNE+dugiXERFsET1JlKZfM5lJDEpSMilKW4bToYJ7pxf0Zne78xyXB2ny2c2aHfJ6WLnz1AaTNHAmQeQ==

"@rails/actioncable@^7.0":
version "7.0.4"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-7.0.4.tgz#70a3ca56809f7aaabb80af2f9c01ae51e1a8ed41"
Expand Down Expand Up @@ -183,3 +195,11 @@ stimulus-read-more@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/stimulus-read-more/-/stimulus-read-more-4.1.0.tgz#f34efb2dcb33fd091936d84c569937bc100506c8"
integrity sha512-SJyCJqZrhDSKpfrepnhStBaxtyv6Jnvr+b84GDg3l+/BzL5HaFLYmc6QkSNCeR6y0x+Zw7lwKuzv+XzyAm1KzQ==

tom-select@^2.2.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/tom-select/-/tom-select-2.2.2.tgz#8e5f9296e6d80254feccb57f0986bd6c44d126e2"
integrity sha512-igGah1yY6yhrnN2h/Ky8I5muw/nE/YQxIsEZoYu5qaA4bsRibvKto3s8QZZosKpOd0uO8fNYhRfAwgHB4IAYew==
dependencies:
"@orchidjs/sifter" "^1.0.3"
"@orchidjs/unicode-variants" "^1.0.4"