# frozen_string_literal: true module Ariadne module Forms # :nodoc: class Base extend ActsAsComponent renders_template File.join(__dir__, "base.html.erb"), :render_base_form class << self attr_reader :has_after_content, :__vcf_form_block, :__vcf_builder alias_method :after_content?, :has_after_content def form(&block) @__vcf_form_block = block end def new(builder, **options) if builder && !builder.is_a?(Ariadne::Forms::Builder) raise ArgumentError, "please pass an instance of Ariadne::Forms::Builder when " \ "constructing a form object (consider using the `ariadne_form_with` helper)" end allocate.tap do |form| form.instance_variable_set(:@builder, builder) form.send(:initialize, **options) end end def inherited(base) form_path = Ariadne::Forms::Utils.const_source_location(base.name) return unless form_path base.template_root_path = File.join(File.dirname(form_path), base.name.demodulize.underscore) base.renders_template("after_content.html.erb") do base.instance_variable_set(:@has_after_content, true) end base.renders_templates("*_caption.html.erb") do |path| base.fields_with_caption_templates << File.basename(path).chomp("_caption.html.erb").to_sym end end def caption_template?(field_name) fields_with_caption_templates.include?(sanitize_field_name_for_template_path(field_name)) end def fields_with_caption_templates @fields_with_caption_templates ||= [] end def sanitize_field_name_for_template_path(field_name) field_name.to_s.delete_suffix("?").to_sym end end def inputs @inputs ||= form_object.inputs.map do |input| next input unless input.input? # wrap inputs in a group (unless they are already groups) if input.type == :group input else Ariadne::Forms::Dsl::InputGroup.new(builder: @builder, form: self) do |group| group.send(:add_input, input) end end end end def each_input_in(root_input, &block) return enum_for(__method__, root_input) unless block root_input.inputs.each do |input| if input.respond_to?(:inputs) each_input_in(input, &block) else yield input end end end def before_render each_input_in(self) do |input| if input.input? && input.invalid? && input.focusable? input.autofocus! break end end end def caption_template?(*args) self.class.caption_template?(*args) end def after_content?(*args) self.class.after_content?(*args) end def render_caption_template(field_name) send(:"render_#{self.class.sanitize_field_name_for_template_path(field_name)}_caption") end def perform_render(&_block) return "" unless render? Base.compile! self.class.compile! render_base_form end def render? true end private def form_object @__pf_form_object ||= Ariadne::Forms::Dsl::FormObject.new(builder: @builder, form: self).tap do |obj| # compile before adding inputs so caption templates are identified self.class.compile! instance_exec(obj, &self.class.__vcf_form_block) end # rubocop:enable Naming/MemoizedInstanceVariableName end end end end