Skip to content

Support maxlength HTML element for text_field component #204

@dennismonsewicz

Description

@dennismonsewicz

As a developer, who is creating a form with a max length requirement for an input field, I would like the ability to pass in a maxlength attribute when creating a text_field.

Proposed Change

Component Class

require 'voom/presenters/dsl/components/input'

module Voom
  module Presenters
    module DSL
      module Components
        class TextField < Input

          attr_reader :required, :full_width, :password, :auto_complete

          def initialize(**attribs_, &block)
            super(type: :text_field, **attribs_, &block)
            @required = attribs.delete(:required){ false }
            @full_width = attribs.delete(:full_width){ true }
            @password = attribs.delete(:password){ false }
            @maxlength = attribs.delete(:maxlength) { nil }
            @auto_complete = validate_auto_complete(attribs.delete(:auto_complete) { :off })
            label(attribs.delete(:label))if attribs.key?(:label)
            value(attribs.delete(:value))if attribs.key?(:value)
            expand!
          end

          def label(text=nil)
            return @label if locked?
            @label = text
          end

          def icon(icon=nil, **attribs, &block)
            return @icon if locked?
            @icon = Components::Icon.new(parent: self, icon: icon, position: attribs.delete(:position){:right},
                                         **attribs, &block)
          end

          def value(value=nil)
            return @value if locked?
            @value = value
          end

          def pattern(pattern=nil)
            return @pattern if locked?
            @pattern = json_regexp(Regexp.new(pattern))
          end

          def hint(hint=nil)
            return @hint if locked?
            @hint = hint
          end

          def error(error=nil)
            return @error if locked?
            @error = error
          end

          private
          def json_regexp(regexp)
            str = regexp.inspect.
                sub('\\A', '^').
                sub('\\Z', '$').
                sub('\\z', '$').
                sub(/^\//, '').
                sub(/\/[a-z]*$/, '').
                gsub(/\(\?#.+\)/, '').
                gsub(/\(\?-\w+:/, '(').
                gsub(/\s/, '')
            Regexp.new(str).source
          end

          def validate_auto_complete(value)
            case value
            when false, :disabled, 'disabled', 'off', nil
              :off
            when true, :enabled, 'enabled', 'on'
              :on
            else # :on, :off, client-specific values
              value
            end
          end
        end
      end
    end
  end
end

Component HTML

<% if comp
     leading_icon = comp.icon && comp.icon.position.select {|p| eq(p, :left)}.any?
     trailing_icon = comp.icon && comp.icon.position.select {|p| eq(p, :right)}.any?
     auto_complete = comp.auto_complete&.to_sym == :off ? 'extra-off' : comp.auto_complete
%>
  <div id="<%= comp.id %>"
       <% if comp.tag %>data-input-tag="<%= comp.tag %>"<% end %>
       <% if comp.dirtyable %>data-dirtyable<% end %>
       class="v-input v-text-field v-focusable mdc-text-field mdc-text-field--outlined
            <%= 'mdc-text-field--with-leading-icon' if leading_icon %>
            <%= 'mdc-text-field--with-trailing-icon' if trailing_icon %>
            <%= 'mdc-text-field--disabled' if comp.disabled %>
            <%= 'is-invalid is-dirty' if comp.error %>"
       style="<%= 'width:100%' if comp.full_width %>">

    <input id="<%= comp.id %>-input"
           name="<%= comp.name %>"
           type="<%= comp.password ? 'password' : 'text' %>"
           value="<%= comp.value %>"
           class="mdc-text-field__input"
           aria-controls="<%= comp.id %>-input-helper-text"
           <% if comp.disabled %>disabled<% end %>
           <%= 'required' if comp.required %>
           <%= 'invalid' if comp.error %>
           <%= "pattern='#{comp.pattern}'" if comp.pattern %>
           <%= "maxlength='#{comp.maxlength}'" if comp.maxlength %>
           autocomplete="<%= auto_complete %>"
           list="<%= comp.id %>-list"
           <%= erb :"components/event", :locals => {comp: comp, events: comp.events, parent_id:  "#{comp.id}-input"} %>>

    <%= erb :"components/icon", :locals => {comp: comp.icon, class_name: 'mdc-text-field__icon', parent_id: "#{comp.id}-input"} %>

    <div class="mdc-notched-outline">
      <div class="mdc-notched-outline__leading"></div>
      <div class="mdc-notched-outline__notch">
        <label for="<%= comp.id %>-input" class="mdc-floating-label"><%= comp.label %></label>
      </div>
      <div class="mdc-notched-outline__trailing"></div>
    </div>
    <datalist id="<%= comp.id %>-list">
    </datalist>
  </div>
  <% if comp.error || comp.hint %>
    <p id="<%= comp.id %>-input-helper-text" class="mdc-text-field-helper-text mdc-text-field-helper-text--persistent mdc-text-field-helper-text--validation-msg" aria-hidden="true">
      <%= comp.error || comp.hint %>
    </p>
  <% end %>
  <%= erb :"components/tooltip", :locals => {comp: comp.tooltip, parent_id: comp.id} %>
<% end %>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions