diff --git a/lib/superform/rails/components/checkbox.rb b/lib/superform/rails/components/checkbox.rb index 0c40f73..09c3746 100644 --- a/lib/superform/rails/components/checkbox.rb +++ b/lib/superform/rails/components/checkbox.rb @@ -2,6 +2,8 @@ module Superform module Rails module Components class Checkbox < Field + prepend Concerns::Requirable + def view_template(&) # Rails has a hidden and checkbox input to deal with sending back a value # to the server regardless of if the input is checked or not. @@ -16,4 +18,4 @@ def field_attributes end end end -end \ No newline at end of file +end diff --git a/lib/superform/rails/components/concerns/requirable.rb b/lib/superform/rails/components/concerns/requirable.rb new file mode 100644 index 0000000..b8425eb --- /dev/null +++ b/lib/superform/rails/components/concerns/requirable.rb @@ -0,0 +1,24 @@ +module Superform + module Rails + module Components + module Concerns + module Requirable + def field_attributes + super.merge(validation_attributes) + end + + def validation_attributes + return {} unless presence_validated? + { required: true } + end + + def presence_validated? + object = field.parent&.object + return false unless object&.class&.respond_to?(:validators_on) + object.class.validators_on(field.key).any? { |v| v.kind == :presence } + end + end + end + end + end +end diff --git a/lib/superform/rails/components/input.rb b/lib/superform/rails/components/input.rb index 02e40b4..cee564d 100644 --- a/lib/superform/rails/components/input.rb +++ b/lib/superform/rails/components/input.rb @@ -2,6 +2,8 @@ module Superform module Rails module Components class Input < Field + prepend Concerns::Requirable + def view_template(&) input(**attributes) end @@ -56,4 +58,4 @@ def attribute_type end end end -end \ No newline at end of file +end diff --git a/lib/superform/rails/components/select.rb b/lib/superform/rails/components/select.rb index 8979591..5c86b8b 100644 --- a/lib/superform/rails/components/select.rb +++ b/lib/superform/rails/components/select.rb @@ -2,6 +2,8 @@ module Superform module Rails module Components class Select < Field + prepend Concerns::Requirable + def initialize(*, collection: [], **, &) super(*, **, &) @collection = collection @@ -40,4 +42,4 @@ def map_options(collection) end end end -end \ No newline at end of file +end diff --git a/lib/superform/rails/components/textarea.rb b/lib/superform/rails/components/textarea.rb index 27357db..2667a74 100644 --- a/lib/superform/rails/components/textarea.rb +++ b/lib/superform/rails/components/textarea.rb @@ -2,6 +2,8 @@ module Superform module Rails module Components class Textarea < Field + prepend Concerns::Requirable + def view_template(&content) content ||= Proc.new { dom.value } textarea(**attributes, &content) @@ -9,4 +11,4 @@ def view_template(&content) end end end -end \ No newline at end of file +end diff --git a/spec/superform/rails/field_convenience_methods_spec.rb b/spec/superform/rails/field_convenience_methods_spec.rb index c3d9196..fff58a3 100644 --- a/spec/superform/rails/field_convenience_methods_spec.rb +++ b/spec/superform/rails/field_convenience_methods_spec.rb @@ -60,4 +60,78 @@ expect(component.type).to eq("radio") end end -end \ No newline at end of file + + describe "HTML5 client-side validations" do + context "input" do + it "adds required when presence validation exists" do + component = field.input + expect(component.field_attributes[:required]).to eq(true) + end + + it "does not add required when no presence validation" do + component = form.field(:last_name).input + expect(component.field_attributes.key?(:required)).to eq(false) + end + + it "allows required: false to override" do + component = field.input(required: false) + attrs = component.send(:attributes) + expect(attrs[:required]).to eq(false) + end + end + + context "checkbox" do + it "adds required when presence validation exists" do + component = field.checkbox + expect(component.field_attributes[:required]).to eq(true) + end + + it "does not add required when no presence validation" do + component = form.field(:last_name).checkbox + expect(component.field_attributes.key?(:required)).to eq(false) + end + + it "allows required: false to override" do + component = field.checkbox(required: false) + attrs = component.send(:attributes) + expect(attrs[:required]).to eq(false) + end + end + + context "textarea" do + it "adds required when presence validation exists" do + component = field.textarea + expect(component.field_attributes[:required]).to eq(true) + end + + it "does not add required when no presence validation" do + component = form.field(:last_name).textarea + expect(component.field_attributes.key?(:required)).to eq(false) + end + + it "allows required: false to override" do + component = field.textarea(required: false) + attrs = component.send(:attributes) + expect(attrs[:required]).to eq(false) + end + end + + context "select" do + it "adds required when presence validation exists" do + component = field.select("a", "b") + expect(component.field_attributes[:required]).to eq(true) + end + + it "does not add required when no presence validation" do + component = form.field(:last_name).select("a", "b") + expect(component.field_attributes.key?(:required)).to eq(false) + end + + it "allows required: false to override" do + component = field.select("a", "b", required: false) + attrs = component.send(:attributes) + expect(attrs[:required]).to eq(false) + end + end + end +end