Creating FormTag as Shopify using Liquid Block

If you using Liquid Filter do you know the Shopify is reference to Ecommerce platform on the web and they created and using Liquid Markup

To create like the same behave using simple form ou form_for on the RoR using the Liquid do you must need to created a Liquid Block

In shopify’s explanation {% form ‘example’ %} is informed it only generate elements html to submit but looking carefully the shopify’s form tag does more than that.

a) add  the value post when the render is back

b) add “error” on the class element in the inputs

Screen Shot 2015-12-27 at 13.54.35

This is the way I generate html input with my form block

#/customers/new.html.liquid

{% form 'form_customer' %}
form id=create_customer method=post action=/customers accept-charset=UTF-8
  input type=hidden value={{ _csrf_token }} name=authenticity_token/
  input name=_method type=hidden value=post
  input type=hidden value= name=utf8/
  input name=customer[name] title=Please enter your username (at least 3 characters) type=text class=form-control placeholder=Enter name required minlength=3
{% endform %}

#form_tag.rb on gist

require 'i18n'

class FormTag < Liquid::Block
  Syntax     = /(#{Liquid::QuotedFragment})\s*(by\s*(\d+))?/
  def initialize(tag_name, markup, tokens)
     @param_name = Liquid::Expression.parse(markup).name.gsub(form_, )
     super
  end

  def form_nested(params, index, object, html_name)
    attribute = index.gsub(_attributes, )
    object = object.send(attribute)
    params[index].each do |index, key|
      html_name = html_name << [#{index}]
      element = @doc.at(input[@name='#{html_name}'])
      form_nested(params[index], index, object, html_name) if index.include?(attributes)
      form_error(object, index, element)
    end
  end

  def form_error(object, index, element)
    if object.respond_to?(index) and object.errors[index].any? and not element.nil?
      klass = element.get_attribute(:class)
      element.set_attribute(:class, error #{klass})
    end
  end

  def render(context)
    params = context.registers[:controller].env[rack.request.form_hash]
    unless params.nil?
      @object = context.registers[:action_view].assigns[@param_name]
      @doc = Hpricot(super)  # calling `super` returns the content of the block
      params[@param_name].each do |index, key|
        if params[_method].downcase == post
          html_name = #{@param_name}[#{index}]
          unless @object.valid?
            if index.include?(attributes)
              form_nested(params[@param_name], index, @object, html_name)
            else
              element = @doc.at(input[@name='#{html_name}'])
              form_error(@object, index, element)
            end
          end
          @doc.search(input[@name='#{@param_name}[#{index}]']).each do |element|
            element.set_attribute(:value, key) unless element.get_attribute(:type) == radio
          end
        else
          next
        end
      end
      @doc
    else
      super
    end
  end
end

Liquid::Template.register_tag('form', FormTag)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s