# Terminal
rails g scaffold users name age:integer driver_license:boolean extend_profile:boolean twitter linkedin perferred_method_of_contact email phone
rails g stimulus toggle-fields
# settings.json
"inlineFold.regex": "(class=|className=|class:\\s*)(({(`|))|(['\"`]))(.*?)(\\2|(\\4)})",
# app/models/user.rb
class User < ApplicationRecord
enum :perferred_method_of_contact, { email: 0, phone: 1 }
end
# app/views/users/_form.html.erb
<%= form_with(model: user) do |form| %>
<% if user.errors.any? %>
<div style="color: red">
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% user.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="mb-3">
<%= form.label :name, class: 'form-label' %>
<%= form.text_field :name, class: 'form-control' %>
</div>
<div data-controller="toggle-fields">
<div class="mb-3">
<%= form.label :age, class: 'form-label' %>
<%= form.number_field :age, "data-toggle-fields-target": :input, class: 'form-control' %>
</div>
<div data-toggle-fields-target="hidden" data-greater-than=16 class="mb-3 form-check">
<%= form.label :driver_license, class: 'form-check-label' %>
<%= form.check_box :driver_license, class: 'form-check-input' %>
</div>
</div>
<div data-controller="toggle-fields">
<div class="mb-3 form-check">
<%= form.label :extend_profile, class: 'form-check-label' %>
<%= form.check_box :extend_profile, "data-toggle-fields-target": :input, class: 'form-check-input' %>
</div>
<div data-toggle-fields-target="hidden" data-value=true class="mb-3">
<%= form.label :twitter, class: 'form-label' %>
<%= form.text_field :twitter, class: 'form-control' %>
</div>
<div data-toggle-fields-target="hidden" data-value=true class="mb-3">
<%= form.label :linkedin, class: 'form-label' %>
<%= form.text_field :linkedin, class: 'form-control' %>
</div>
</div>
<div data-controller="toggle-fields">
<div class="mb-3">
<%= form.label :perferred_method_of_contact, class: 'form-label' %>
<%= form.select :perferred_method_of_contact,
User.perferred_method_of_contacts.keys,
{ include_blank: true },
"data-toggle-fields-target": :input,
class: 'form-control' %>
</div>
<div data-toggle-fields-target="hidden" data-value="email" class="mb-3">
<%= form.label :email, class: 'form-label' %>
<%= form.text_field :email, class: 'form-control' %>
</div>
<div data-toggle-fields-target="hidden" data-value="phone" class="mb-3">
<%= form.label :phone, class: 'form-label' %>
<%= form.text_field :phone, class: 'form-control' %>
</div>
</div>
<div class="actions">
<%= form.submit class: 'btn btn-primary' %>
</div>
<% end %>
# app/javascript/controllers/toggle_fields_controller.js
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="toggle-fields"
export default class extends Controller {
static targets = ["hidden", "input"]
connect() {
this.inputTarget.addEventListener("change", this.toggle.bind(this))
this.inputTarget.addEventListener("keyup", this.toggle.bind(this))
this.toggle()
}
disconnect() {
this.inputTarget.removeEventListener("change", this.toggle.bind(this))
this.inputTarget.removeEventListener("keyup", this.toggle.bind(this))
}
toggle() {
this.hiddenTargets.forEach((target) => {
const targetValue = target.dataset.value ? target.dataset.value : null
const greaterThanValue = target.dataset.greaterThan ? parseFloat(target.dataset.greaterThan) : null
const lessThanValue = target.dataset.lessThan ? parseFloat(target.dataset.lessThan) : null
console.log(this.value, targetValue, greaterThanValue, lessThanValue);
let shouldShow = true
if (targetValue !== null && this.value !== targetValue) { shouldShow = false }
if (greaterThanValue !== null && this.value < greaterThanValue) { shouldShow = false }
if (lessThanValue !== null && this.value > lessThanValue) { shouldShow = false }
if (shouldShow) {
target.classList.remove("d-none")
// target.classList.remove("hidden", "sm:hidden", "md:hidden", "lg:hidden")
} else {
target.classList.add("d-none")
// target.classList.add("hidden", "sm:hidden", "md:hidden", "lg:hidden")
}
})
}
get value() {
switch (this.inputTarget.type) {
case "checkbox":
return this.inputTarget.checked ? "true" : "false"
case "number":
return this.inputTarget.value ? parseFloat(this.inputTarget.value) : null
default:
return this.inputTarget.value
}
}
}