mkhairi / materialize-sass

Materializecss rubygem for Rails Asset Pipeline / Sprockets
http://materialize.labs.my/
MIT License
805 stars 243 forks source link

How do I fix the incompatibilities between Rails and Materialize? #93

Closed rlugge closed 8 years ago

rlugge commented 8 years ago

Materialize and Rails operate on such completely different assumptions, how can I overcome the issues that result?

Examples include many form elements not performing correctly due to turbolinks breaking Materialize's $(document).ready() code and built-in error handling breaking Materialize's class-structure requirements.

lebart commented 8 years ago

Hi rlugge,

I run apps in rails with this gem and I have no problem at all. Can you explain your incompatibilities?

For the turbo link problem you've a gem (jquery-turbolink I believe) or you can do something like this:

var formsInit = function() {
    $('select').material_select();
};
$(document).ready(formsInit) //standard jQuery behavior
$(document).on('page:load', formsInit) //adaptation to turbolinks
rlugge commented 8 years ago

I'm well aware of using page:load as well as document.ready for initializers. Problem is, there aren't any initializers for the standard text input + label behaviour. It just 'happens', magically. You have to turn off turbolinks to fix.

The second issue is the way rails forms wrap erroring text fields & labels in validation error divs -- which immediately breaks the requirement that .input-field be on the parent div, with both input and label in the same div.

lebart commented 8 years ago

I didn't turn off tubolinks in the app where I use this gem, I not sure to completely understand your needs.

For the rails validations process I do something like this:

An initializer for adding the class I need

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  class_attr_index = html_tag.index 'class="'

  if class_attr_index
    html_tag.insert class_attr_index+7, 'validation--failed invalid '
  else
    html_tag.insert html_tag.index('>'), ' class="validation--failed invalid"'
  end
end

And a js file for form elements

//  highlight the text fields when invalid
var formElementsInit = function() {
  // field validations
  $("input:file.validation--failed").parents('input-field').find("input:text.file-path").first().addClass('validation--failed invalid');

  // update labels if there's content
  Materialize.updateTextFields();
};
$(document).ready(formElementsInit) //standard jQuery behavior
$(document).on('page:load', formElementsInit) //adaptation to turbolinks

Hope this helps

lebart commented 8 years ago

ps: I also see your questions on stackoverflow I'll put some answers there too. (about .containers)

rlugge commented 8 years ago

Just noticed I forgot to add my solutions here. Some are similar to your suggestions. Others are not.

First, disable turbolinks.

Second, change Rails error handling by adding the following code (very similar to what you posted):

config.action_view.field_error_proc = Proc.new { |html_tag, instance| 
  if html_tag =~ /<(input|label|textarea|select)/
    html_field = Nokogiri::HTML::DocumentFragment.parse(html_tag)
    html_field.children.add_class 'invalid'
    html_field.to_s.html_safe
  else
    html_tag
  end
}
hoffmanilya commented 7 years ago

You can also add this to have the error message show up the 'error' label. Note: the 'autofocus' on the input is necessary for the styling of the error label.

    html_field.children.each do |child|
      if child.name == 'label'
        child.set_attribute 'data-error', instance.error_message.join(', ').capitalize
      else
        child.set_attribute 'autofocus', true
      end
    end