bootstrap_form 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +21 -8
- data/.gitignore +4 -2
- data/.rubocop.yml +2 -1
- data/.yarnrc +5 -0
- data/CHANGELOG.md +11 -3
- data/CONTRIBUTING.md +101 -14
- data/Dangerfile +4 -4
- data/Dockerfile +5 -5
- data/Gemfile +5 -21
- data/README.md +68 -21
- data/RELEASING.md +12 -1
- data/Rakefile +7 -6
- data/bootstrap_form.gemspec +6 -8
- data/docker-compose.yml +6 -24
- data/gemfiles/6.0.gemfile +1 -1
- data/gemfiles/6.1.gemfile +1 -1
- data/gemfiles/7.0.gemfile +2 -3
- data/gemfiles/common.gemfile +28 -0
- data/gemfiles/edge.gemfile +3 -2
- data/lib/bootstrap_form/components/labels.rb +3 -9
- data/lib/bootstrap_form/components/validation.rb +36 -19
- data/lib/bootstrap_form/form_builder.rb +3 -0
- data/lib/bootstrap_form/form_group.rb +9 -6
- data/lib/bootstrap_form/form_group_builder.rb +10 -7
- data/lib/bootstrap_form/helpers/bootstrap.rb +7 -8
- data/lib/bootstrap_form/helpers/field.rb +26 -0
- data/lib/bootstrap_form/helpers.rb +1 -0
- data/lib/bootstrap_form/inputs/check_box.rb +22 -6
- data/lib/bootstrap_form/inputs/radio_button.rb +3 -3
- data/lib/bootstrap_form/version.rb +2 -1
- data/lib/bootstrap_form.rb +1 -1
- metadata +14 -146
- data/demo/.postcssrc.yml +0 -3
- data/demo/.ruby-version +0 -1
- data/demo/Gemfile +0 -80
- data/demo/Gemfile.lock +0 -261
- data/demo/Procfile.dev +0 -2
- data/demo/README.md +0 -17
- data/demo/Rakefile +0 -6
- data/demo/app/assets/builds/.keep +0 -0
- data/demo/app/assets/builds/application.js.LICENSE.txt +0 -9
- data/demo/app/assets/config/manifest.js +0 -2
- data/demo/app/assets/stylesheets/actiontext.css +0 -31
- data/demo/app/assets/stylesheets/actiontext.scss +0 -38
- data/demo/app/assets/stylesheets/application.scss +0 -1
- data/demo/app/controllers/application_controller.rb +0 -2
- data/demo/app/controllers/bootstrap_controller.rb +0 -29
- data/demo/app/controllers/users_controller.rb +0 -9
- data/demo/app/helpers/bootstrap_helper.rb +0 -27
- data/demo/app/javascript/application.js +0 -3
- data/demo/app/javascript/channels/consumer.js +0 -6
- data/demo/app/javascript/channels/index.js +0 -5
- data/demo/app/javascript/packs/application.js +0 -11
- data/demo/app/models/address.rb +0 -3
- data/demo/app/models/application_record.rb +0 -3
- data/demo/app/models/faux_user.rb +0 -9
- data/demo/app/models/skill.rb +0 -15
- data/demo/app/models/super_user.rb +0 -2
- data/demo/app/models/user.rb +0 -25
- data/demo/app/views/active_storage/blobs/_blob.html.erb +0 -14
- data/demo/app/views/bootstrap/form.html.erb +0 -67
- data/demo/app/views/layouts/action_text/contents/_content.html.erb +0 -3
- data/demo/app/views/layouts/application.html.erb +0 -76
- data/demo/bin/bundle +0 -3
- data/demo/bin/dev +0 -9
- data/demo/bin/rails +0 -4
- data/demo/bin/rake +0 -4
- data/demo/bin/setup +0 -36
- data/demo/bin/update +0 -31
- data/demo/bin/webpack +0 -15
- data/demo/bin/webpack-dev-server +0 -15
- data/demo/bin/yarn +0 -11
- data/demo/config/application.rb +0 -21
- data/demo/config/boot.rb +0 -5
- data/demo/config/database.yml +0 -21
- data/demo/config/environment.rb +0 -5
- data/demo/config/environments/development.rb +0 -60
- data/demo/config/environments/production.rb +0 -48
- data/demo/config/environments/test.rb +0 -46
- data/demo/config/initializers/application_controller_renderer.rb +0 -8
- data/demo/config/initializers/backtrace_silencers.rb +0 -7
- data/demo/config/initializers/cookies_serializer.rb +0 -5
- data/demo/config/initializers/filter_parameter_logging.rb +0 -4
- data/demo/config/initializers/inflections.rb +0 -16
- data/demo/config/initializers/mime_types.rb +0 -4
- data/demo/config/initializers/wrap_parameters.rb +0 -14
- data/demo/config/locales/en.yml +0 -33
- data/demo/config/puma.rb +0 -56
- data/demo/config/routes.rb +0 -6
- data/demo/config/spring.rb +0 -6
- data/demo/config/storage.yml +0 -35
- data/demo/config/webpack/development.js +0 -5
- data/demo/config/webpack/environment.js +0 -3
- data/demo/config/webpack/production.js +0 -5
- data/demo/config/webpack/test.js +0 -5
- data/demo/config/webpacker.yml +0 -92
- data/demo/config.ru +0 -5
- data/demo/db/schema.rb +0 -84
- data/demo/doc/screenshots/bootstrap/index/00_horizontal_form.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/01_with_validation_error.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/02_inline_form.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/03_simple_action_text_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/index/04_floating_labels.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/00_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/01_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/02_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/03_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/04_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/05_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/06_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/07_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/08_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/09_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/10_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/11_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/12_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/13_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/14_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/15_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/16_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/17_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/18_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/19_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/20_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/21_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/22_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/23_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/24_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/25_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/26_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/27_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/28_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/29_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/30_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/31_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/32_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/33_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/34_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/35_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/36_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/37_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/38_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/39_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/40_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/41_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/42_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/43_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/44_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/45_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/46_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/47_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/48_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/49_example.png +0 -0
- data/demo/doc/screenshots/bootstrap/readme/50_example.png +0 -0
- data/demo/log/.keep +0 -0
- data/demo/package.json +0 -21
- data/demo/public/favicon.ico +0 -0
- data/demo/test/application_system_test_case.rb +0 -8
- data/demo/test/controllers/bootstrap_controller_test.rb +0 -8
- data/demo/test/controllers/users_controller_test.rb +0 -13
- data/demo/test/fixtures/action_text/rich_texts.yml +0 -4
- data/demo/test/fixtures/users.yml +0 -2
- data/demo/test/system/bootstrap_test.rb +0 -84
- data/demo/test/test_helper.rb +0 -10
- data/demo/webpack.config.js +0 -20
- data/demo/yarn.lock +0 -7176
- data/gemfiles/5.2.gemfile +0 -4
data/Rakefile
CHANGED
|
@@ -17,12 +17,13 @@ end
|
|
|
17
17
|
|
|
18
18
|
require 'bundler/gem_tasks'
|
|
19
19
|
|
|
20
|
-
require
|
|
20
|
+
require "minitest/test_task"
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
t.libs <<
|
|
24
|
-
t.
|
|
25
|
-
t.
|
|
22
|
+
Minitest::TestTask.create(:test) do |t|
|
|
23
|
+
t.libs << "test"
|
|
24
|
+
t.libs << "lib"
|
|
25
|
+
t.warning = false
|
|
26
|
+
t.test_globs = ["test/**/*_test.rb"]
|
|
26
27
|
end
|
|
27
28
|
|
|
28
29
|
# This automatically updates GitHub Releases whenever we `rake release` the gem
|
|
@@ -34,4 +35,4 @@ end
|
|
|
34
35
|
desc 'Run RuboCop checks'
|
|
35
36
|
RuboCop::RakeTask.new(:rubocop)
|
|
36
37
|
|
|
37
|
-
task default: %i[test rubocop]
|
|
38
|
+
task default: %i[test rubocop:autocorrect]
|
data/bootstrap_form.gemspec
CHANGED
|
@@ -3,30 +3,28 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
3
3
|
|
|
4
4
|
require "bootstrap_form/version"
|
|
5
5
|
|
|
6
|
-
REQUIRED_RAILS_VERSION = ">= 5.2".freeze
|
|
7
|
-
|
|
8
6
|
Gem::Specification.new do |s|
|
|
9
7
|
s.name = "bootstrap_form"
|
|
10
8
|
s.version = BootstrapForm::VERSION
|
|
11
9
|
s.authors = ["Stephen Potenza", "Carlos Lopes"]
|
|
12
10
|
s.email = ["potenza@gmail.com", "carlos.el.lopes@gmail.com"]
|
|
13
11
|
s.homepage = "https://github.com/bootstrap-ruby/bootstrap_form"
|
|
14
|
-
s.summary = "Rails form builder that makes it easy to style forms using "\
|
|
12
|
+
s.summary = "Rails form builder that makes it easy to style forms using " \
|
|
15
13
|
"Bootstrap 5"
|
|
16
|
-
s.description = "bootstrap_form is a rails form builder that makes it super "\
|
|
14
|
+
s.description = "bootstrap_form is a rails form builder that makes it super " \
|
|
17
15
|
"easy to create beautiful-looking forms using Bootstrap 5"
|
|
18
16
|
s.license = "MIT"
|
|
19
17
|
s.metadata = { "rubygems_mfa_required" => "true" }
|
|
20
18
|
|
|
21
19
|
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
22
|
-
f.match(%r{^(test)/})
|
|
20
|
+
f.match(%r{^(test)/|^(demo)/})
|
|
23
21
|
end
|
|
24
22
|
|
|
25
23
|
s.bindir = "exe"
|
|
26
24
|
s.require_paths = ["lib"]
|
|
27
25
|
|
|
28
|
-
s.required_ruby_version = ">=
|
|
26
|
+
s.required_ruby_version = ">= 3.0"
|
|
29
27
|
|
|
30
|
-
s.add_dependency("actionpack", REQUIRED_RAILS_VERSION)
|
|
31
|
-
s.add_dependency("activemodel", REQUIRED_RAILS_VERSION)
|
|
28
|
+
s.add_dependency("actionpack", BootstrapForm::REQUIRED_RAILS_VERSION)
|
|
29
|
+
s.add_dependency("activemodel", BootstrapForm::REQUIRED_RAILS_VERSION)
|
|
32
30
|
end
|
data/docker-compose.yml
CHANGED
|
@@ -5,9 +5,10 @@ services:
|
|
|
5
5
|
build:
|
|
6
6
|
context: .
|
|
7
7
|
args:
|
|
8
|
-
NODE_MAJOR:
|
|
9
|
-
YARN_VERSION:
|
|
10
|
-
|
|
8
|
+
NODE_MAJOR: "12"
|
|
9
|
+
YARN_VERSION: "1.22.4"
|
|
10
|
+
RUBY_VERSION: ${RUBY_VERSION}
|
|
11
|
+
image: bootstrap-form:latest-$RUBY_VERSION
|
|
11
12
|
tmpfs:
|
|
12
13
|
- /tmp
|
|
13
14
|
|
|
@@ -17,15 +18,6 @@ services:
|
|
|
17
18
|
tty: true
|
|
18
19
|
volumes:
|
|
19
20
|
- .:/app:cached
|
|
20
|
-
# - rails_cache:/app/tmp/cache
|
|
21
|
-
# - bundle:/app/vendor/bundle
|
|
22
|
-
# - node_modules:/app/node_modules
|
|
23
|
-
# - packs:/app/public/packs
|
|
24
|
-
- /etc/passwd:/etc/passwd:ro
|
|
25
|
-
# One or the other of the following lines might be redundant, or one might be
|
|
26
|
-
# better than the other.
|
|
27
|
-
- ~/.ssh:${HOME}/.ssh
|
|
28
|
-
- ${SSH_AUTH_SOCK}:/ssh-agent
|
|
29
21
|
environment:
|
|
30
22
|
- SSH_AUTH_SOCK=/ssh-agent
|
|
31
23
|
- NODE_ENV=development
|
|
@@ -34,16 +26,6 @@ services:
|
|
|
34
26
|
- WEBPACKER_DEV_SERVER_HOST=webpacker
|
|
35
27
|
- WEB_CONCURRENCY=1
|
|
36
28
|
- HISTFILE=/app/.bash_history
|
|
29
|
+
ports:
|
|
30
|
+
- "3000:3000"
|
|
37
31
|
command: /bin/bash
|
|
38
|
-
|
|
39
|
-
# server:
|
|
40
|
-
# <<: *shell
|
|
41
|
-
# command: sh -c "cd demo/app && bundle exec rails server -b 0.0.0.0"
|
|
42
|
-
# ports:
|
|
43
|
-
# - '3000:3000'
|
|
44
|
-
|
|
45
|
-
# volumes:
|
|
46
|
-
# bundle:
|
|
47
|
-
# node_modules:
|
|
48
|
-
# rails_cache:
|
|
49
|
-
# packs:
|
data/gemfiles/6.0.gemfile
CHANGED
data/gemfiles/6.1.gemfile
CHANGED
data/gemfiles/7.0.gemfile
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
gems = "#{
|
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
|
2
2
|
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
3
|
|
|
4
|
-
# 7.0.0 has an issue with Ruby 3.1.
|
|
5
|
-
# And a test case has an issue with 7.0.1
|
|
6
4
|
gem "rails", "~> 7.0.2"
|
|
5
|
+
gem "sprockets-rails", require: "sprockets/railtie"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
source "http://rubygems.org"
|
|
2
|
+
|
|
3
|
+
gemspec path: File.dirname(__dir__)
|
|
4
|
+
|
|
5
|
+
# To test with different Rails versions, use the files in `./gemfiles`
|
|
6
|
+
|
|
7
|
+
group :development do
|
|
8
|
+
gem "htmlbeautifier"
|
|
9
|
+
gem "puma"
|
|
10
|
+
gem "rubocop-performance", require: false
|
|
11
|
+
gem "rubocop-rails", require: false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
group :test do
|
|
15
|
+
gem "diffy"
|
|
16
|
+
gem "equivalent-xml"
|
|
17
|
+
gem "mocha"
|
|
18
|
+
gem "sqlite3"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
group :development, :test do
|
|
22
|
+
gem "debug"
|
|
23
|
+
gem "pry-byebug"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
group :ci do
|
|
27
|
+
gem "danger"
|
|
28
|
+
end
|
data/gemfiles/edge.gemfile
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
gems = "#{
|
|
1
|
+
gems = "#{__dir__}/common.gemfile"
|
|
2
2
|
eval File.read(gems), binding, gems # rubocop: disable Security/Eval
|
|
3
3
|
|
|
4
|
-
gem "rails", git: "https://github.com/rails/rails.git"
|
|
4
|
+
gem "rails", git: "https://github.com/rails/rails.git", branch: "main"
|
|
5
|
+
gem "sprockets-rails", require: "sprockets/railtie"
|
|
@@ -24,14 +24,8 @@ module BootstrapForm
|
|
|
24
24
|
|
|
25
25
|
def label_classes(name, options, custom_label_col, group_layout)
|
|
26
26
|
classes = ["form-label", options[:class], label_layout_classes(custom_label_col, group_layout)]
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
when true
|
|
30
|
-
classes << "required"
|
|
31
|
-
when nil, :default
|
|
32
|
-
classes << "required" if required_attribute?(object, name)
|
|
33
|
-
end
|
|
34
|
-
|
|
27
|
+
classes << "required" if required_field_options(options, name)[:required]
|
|
28
|
+
options.delete(:required)
|
|
35
29
|
classes << "text-danger" if label_errors && error?(name)
|
|
36
30
|
classes.flatten.compact
|
|
37
31
|
end
|
|
@@ -46,7 +40,7 @@ module BootstrapForm
|
|
|
46
40
|
|
|
47
41
|
def label_text(name, options)
|
|
48
42
|
if label_errors && error?(name)
|
|
49
|
-
(options[:text] || object.class.human_attribute_name(name)).to_s
|
|
43
|
+
(options[:text] || object.class.human_attribute_name(name)).to_s + " #{get_error_messages(name)}"
|
|
50
44
|
else
|
|
51
45
|
options[:text] || object&.class.try(:human_attribute_name, name)
|
|
52
46
|
end
|
|
@@ -8,35 +8,45 @@ module BootstrapForm
|
|
|
8
8
|
private
|
|
9
9
|
|
|
10
10
|
def error?(name)
|
|
11
|
-
object.respond_to?(:errors) &&
|
|
11
|
+
name && object.respond_to?(:errors) && (object.errors[name].any? || association_error?(name))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def association_error?(name)
|
|
15
|
+
object.class.reflections.any? do |association_name, a|
|
|
16
|
+
next unless a.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
17
|
+
next unless a.foreign_key == name.to_s
|
|
18
|
+
|
|
19
|
+
object.errors[association_name].any?
|
|
20
|
+
end
|
|
12
21
|
end
|
|
13
22
|
|
|
14
23
|
def required_attribute?(obj, attribute)
|
|
15
24
|
return false unless obj && attribute
|
|
16
25
|
|
|
17
26
|
target = obj.instance_of?(Class) ? obj : obj.class
|
|
27
|
+
return false unless target.respond_to? :validators_on
|
|
18
28
|
|
|
19
|
-
target_validators
|
|
20
|
-
|
|
21
|
-
else
|
|
22
|
-
[]
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
presence_validator?(target_validators)
|
|
29
|
+
presence_validator?(target_validators(target, attribute)) ||
|
|
30
|
+
required_association?(target, attribute)
|
|
26
31
|
end
|
|
27
32
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
has_presence_validator |= target_validators.include?(
|
|
35
|
-
ActiveRecord::Validations::PresenceValidator
|
|
36
|
-
)
|
|
33
|
+
def required_association?(target, attribute)
|
|
34
|
+
target.reflections.find do |name, a|
|
|
35
|
+
next unless a.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
36
|
+
next unless a.foreign_key == attribute.to_s
|
|
37
|
+
|
|
38
|
+
presence_validator?(target_validators(target, name))
|
|
37
39
|
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def target_validators(target, attribute)
|
|
43
|
+
target.validators_on(attribute).map(&:class)
|
|
44
|
+
end
|
|
38
45
|
|
|
39
|
-
|
|
46
|
+
def presence_validator?(target_validators)
|
|
47
|
+
target_validators.include?(ActiveModel::Validations::PresenceValidator) ||
|
|
48
|
+
(defined?(ActiveRecord::Validations::PresenceValidator) &&
|
|
49
|
+
target_validators.include?(ActiveRecord::Validations::PresenceValidator))
|
|
40
50
|
end
|
|
41
51
|
|
|
42
52
|
def inline_error?(name)
|
|
@@ -54,7 +64,14 @@ module BootstrapForm
|
|
|
54
64
|
end
|
|
55
65
|
|
|
56
66
|
def get_error_messages(name)
|
|
57
|
-
object.errors[name]
|
|
67
|
+
messages = object.errors[name]
|
|
68
|
+
object.class.reflections.each do |association_name, a|
|
|
69
|
+
next unless a.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
|
70
|
+
next unless a.foreign_key == name.to_s
|
|
71
|
+
|
|
72
|
+
messages << object.errors[association_name]
|
|
73
|
+
end
|
|
74
|
+
messages.join(", ")
|
|
58
75
|
end
|
|
59
76
|
end
|
|
60
77
|
end
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# require 'bootstrap_form/aliasing'
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Metrics/ClassLength
|
|
3
4
|
module BootstrapForm
|
|
4
5
|
class FormBuilder < ActionView::Helpers::FormBuilder
|
|
5
6
|
attr_reader :layout, :label_col, :control_col, :has_error, :inline_errors,
|
|
6
7
|
:label_errors, :acts_like_form_tag
|
|
7
8
|
|
|
9
|
+
include BootstrapForm::Helpers::Field
|
|
8
10
|
include BootstrapForm::Helpers::Bootstrap
|
|
9
11
|
|
|
10
12
|
include BootstrapForm::FormGroupBuilder
|
|
@@ -130,3 +132,4 @@ module BootstrapForm
|
|
|
130
132
|
end
|
|
131
133
|
end
|
|
132
134
|
end
|
|
135
|
+
# rubocop:enable Metrics/ClassLength
|
|
@@ -32,15 +32,18 @@ module BootstrapForm
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def form_group_content(label, help_text, options, &block)
|
|
35
|
+
def form_group_content(label, help_text, options, &block) # rubocop:disable Metrics/AbcSize
|
|
36
|
+
label ||= ActiveSupport::SafeBuffer.new
|
|
36
37
|
if group_layout_horizontal?(options[:layout])
|
|
37
|
-
|
|
38
|
+
label + tag.div(capture(&block) + help_text, class: form_group_control_class(options))
|
|
38
39
|
else
|
|
40
|
+
content = ActiveSupport::SafeBuffer.new
|
|
39
41
|
# Floating labels need to be rendered after the field
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
content << label unless options[:floating]
|
|
43
|
+
content << capture(&block)
|
|
44
|
+
content << label if options[:floating]
|
|
45
|
+
content << help_text if help_text
|
|
46
|
+
content
|
|
44
47
|
end
|
|
45
48
|
end
|
|
46
49
|
|
|
@@ -28,8 +28,7 @@ module BootstrapForm
|
|
|
28
28
|
def form_group_builder_options(options, method)
|
|
29
29
|
options.symbolize_keys!
|
|
30
30
|
options = convert_form_tag_options(method, options) if acts_like_form_tag
|
|
31
|
-
options
|
|
32
|
-
options
|
|
31
|
+
options.merge!(required_field_options(options, method))
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
def convert_form_tag_options(method, options={})
|
|
@@ -77,11 +76,15 @@ module BootstrapForm
|
|
|
77
76
|
classes
|
|
78
77
|
end
|
|
79
78
|
|
|
80
|
-
def form_group_required(options)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
options
|
|
79
|
+
def form_group_required(options, method)
|
|
80
|
+
if options[:skip_required]
|
|
81
|
+
warn "`:skip_required` is deprecated, use `:required: false` instead"
|
|
82
|
+
false
|
|
83
|
+
elsif options.key?(:required)
|
|
84
|
+
options[:required]
|
|
85
|
+
else
|
|
86
|
+
required_attribute?(object, method)
|
|
87
|
+
end
|
|
85
88
|
end
|
|
86
89
|
|
|
87
90
|
def form_group_css_options(method, html_options, options)
|
|
@@ -30,8 +30,7 @@ module BootstrapForm
|
|
|
30
30
|
if options[:error_summary] == false
|
|
31
31
|
title
|
|
32
32
|
else
|
|
33
|
-
|
|
34
|
-
concat error_summary
|
|
33
|
+
tag.p(title) + error_summary
|
|
35
34
|
end
|
|
36
35
|
end
|
|
37
36
|
end
|
|
@@ -39,9 +38,9 @@ module BootstrapForm
|
|
|
39
38
|
def error_summary
|
|
40
39
|
return unless object.errors.any?
|
|
41
40
|
|
|
42
|
-
tag.ul
|
|
43
|
-
object.errors.full_messages.
|
|
44
|
-
|
|
41
|
+
tag.ul(class: "rails-bootstrap-forms-error-summary") do
|
|
42
|
+
object.errors.full_messages.reduce(ActiveSupport::SafeBuffer.new) do |acc, error|
|
|
43
|
+
acc << tag.li(error)
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
46
|
end
|
|
@@ -83,12 +82,12 @@ module BootstrapForm
|
|
|
83
82
|
end
|
|
84
83
|
|
|
85
84
|
def prepend_and_append_input(name, options, &block)
|
|
86
|
-
options = options.extract!(:prepend, :append, :input_group_class)
|
|
85
|
+
options = options.extract!(:prepend, :append, :input_group_class).compact
|
|
87
86
|
|
|
88
87
|
input = capture(&block) || ActiveSupport::SafeBuffer.new
|
|
89
88
|
|
|
90
89
|
input = attach_input(options, :prepend) + input + attach_input(options, :append)
|
|
91
|
-
input
|
|
90
|
+
input << generate_error(name)
|
|
92
91
|
options.present? &&
|
|
93
92
|
input = tag.div(input, class: ["input-group", options[:input_group_class]].compact)
|
|
94
93
|
input
|
|
@@ -100,7 +99,7 @@ module BootstrapForm
|
|
|
100
99
|
end
|
|
101
100
|
|
|
102
101
|
def input_group_content(content)
|
|
103
|
-
return content if
|
|
102
|
+
return content if content.include?("btn")
|
|
104
103
|
|
|
105
104
|
tag.span(content, class: "input-group-text")
|
|
106
105
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module BootstrapForm
|
|
2
|
+
module Helpers
|
|
3
|
+
module Field
|
|
4
|
+
def required_field_options(options, method)
|
|
5
|
+
required = required_field?(options, method)
|
|
6
|
+
{}.tap do |option|
|
|
7
|
+
option[:required] = required
|
|
8
|
+
option[:aria] = { required: true } if required
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def required_field?(options, method)
|
|
15
|
+
if options[:skip_required]
|
|
16
|
+
warn "`:skip_required` is deprecated, use `:required: false` instead"
|
|
17
|
+
false
|
|
18
|
+
elsif options.key?(:required)
|
|
19
|
+
options[:required]
|
|
20
|
+
else
|
|
21
|
+
required_attribute?(object, method)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -9,14 +9,11 @@ module BootstrapForm
|
|
|
9
9
|
included do
|
|
10
10
|
def check_box_with_bootstrap(name, options={}, checked_value="1", unchecked_value="0", &block)
|
|
11
11
|
options = options.symbolize_keys!
|
|
12
|
-
check_box_options = options.except(:class, :label, :label_class, :error_message, :help,
|
|
13
|
-
:inline, :hide_label, :skip_label, :wrapper, :wrapper_class, :switch)
|
|
14
|
-
check_box_options[:class] = check_box_classes(name, options)
|
|
15
12
|
|
|
16
13
|
tag.div(class: check_box_wrapper_class(options), **options[:wrapper].to_h.except(:class)) do
|
|
17
|
-
html = check_box_without_bootstrap(name, check_box_options, checked_value, unchecked_value)
|
|
18
|
-
html
|
|
19
|
-
html
|
|
14
|
+
html = check_box_without_bootstrap(name, check_box_options(name, options), checked_value, unchecked_value)
|
|
15
|
+
html << check_box_label(name, options, checked_value, &block) unless options[:skip_label]
|
|
16
|
+
html << generate_error(name) if options[:error_message]
|
|
20
17
|
html
|
|
21
18
|
end
|
|
22
19
|
end
|
|
@@ -26,6 +23,13 @@ module BootstrapForm
|
|
|
26
23
|
|
|
27
24
|
private
|
|
28
25
|
|
|
26
|
+
def check_box_options(name, options)
|
|
27
|
+
check_box_options = options.except(:class, :label, :label_class, :error_message, :help,
|
|
28
|
+
:inline, :hide_label, :skip_label, :wrapper, :wrapper_class, :switch)
|
|
29
|
+
check_box_options[:class] = check_box_classes(name, options)
|
|
30
|
+
check_box_options.merge!(required_field_options(options, name))
|
|
31
|
+
end
|
|
32
|
+
|
|
29
33
|
def check_box_label(name, options, checked_value, &block)
|
|
30
34
|
label_name = if options[:multiple]
|
|
31
35
|
check_box_value(name, checked_value)
|
|
@@ -59,6 +63,7 @@ module BootstrapForm
|
|
|
59
63
|
def check_box_label_class(options)
|
|
60
64
|
classes = ["form-check-label"]
|
|
61
65
|
classes << options[:label_class]
|
|
66
|
+
classes << "required" if options[:required]
|
|
62
67
|
classes << hide_class if options[:hide_label]
|
|
63
68
|
classes.flatten.compact
|
|
64
69
|
end
|
|
@@ -72,6 +77,17 @@ module BootstrapForm
|
|
|
72
77
|
classes << options[:wrapper_class].presence
|
|
73
78
|
classes.flatten.compact
|
|
74
79
|
end
|
|
80
|
+
|
|
81
|
+
def checkbox_required(options, method)
|
|
82
|
+
if options[:skip_required]
|
|
83
|
+
warn "`:skip_required` is deprecated, use `:required: false` instead"
|
|
84
|
+
false
|
|
85
|
+
elsif options.key?(:required)
|
|
86
|
+
options[:required]
|
|
87
|
+
else
|
|
88
|
+
required_attribute?(object, method)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
75
91
|
end
|
|
76
92
|
end
|
|
77
93
|
end
|
|
@@ -13,8 +13,8 @@ module BootstrapForm
|
|
|
13
13
|
wrapper_attributes[:class] = radio_button_wrapper_class(options)
|
|
14
14
|
tag.div(**wrapper_attributes) do
|
|
15
15
|
html = radio_button_without_bootstrap(name, value, radio_button_options(name, options))
|
|
16
|
-
html
|
|
17
|
-
html
|
|
16
|
+
html << radio_button_label(name, value, options) unless options[:skip_label]
|
|
17
|
+
html << generate_error(name) if options[:error_message]
|
|
18
18
|
html
|
|
19
19
|
end
|
|
20
20
|
end
|
|
@@ -28,7 +28,7 @@ module BootstrapForm
|
|
|
28
28
|
radio_button_options = options.except(:class, :label, :label_class, :error_message, :help,
|
|
29
29
|
:inline, :hide_label, :skip_label, :wrapper, :wrapper_class)
|
|
30
30
|
radio_button_options[:class] = radio_button_classes(name, options)
|
|
31
|
-
radio_button_options
|
|
31
|
+
radio_button_options.merge!(required_field_options(options, name))
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def radio_button_label(name, value, options)
|
data/lib/bootstrap_form.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# NOTE: The rich_text_area and rich_text_area_tag helpers are defined in a file with a different
|
|
2
2
|
# name and not in the usual autoload-reachable way.
|
|
3
3
|
# The following line is definitely need to make `bootstrap_form` work.
|
|
4
|
-
if
|
|
4
|
+
if Rails::VERSION::STRING > "6"
|
|
5
5
|
require "#{Gem::Specification.find_by_name('actiontext').gem_dir}/app/helpers/action_text/tag_helper"
|
|
6
6
|
end
|
|
7
7
|
require "action_view"
|