IE9 nested simple_form_for with haml - ruby-on-rails

I have a page That starts with a form. Inside that form, I render another page called information. Inside this render I have another render for a modal. This modal is another form. So at this point i have one nested form. This works great in all browsers except IE9. I think what IE9 is trying to do is it sees when the second form is ending, and it also ends the first form, so everything that is after the nested form is screwed up.
Has anyone else ran into this problem? and how do you fix it?
Parent File (form):
= simple_form_for #form do |f|
#the_form
= render 'information', :f => f
.buttons
%input{:name => "submit", :type => "submit", :value => "SUBMIT"}
%input{:name => "cancel", :type => "submit", :value => "Cancel"}
Render information file:
#information
%fieldset
%legend
Form Title
= f.input :form_id, :url => form_name_path, :label => 'Field Name'
= render 'modal'
(the rest of the code here breaks)...
Render modal file:
.modal.hide.fade
.modalBox
%h3
New Form Name
%a{href: "#", class: "x", title: "Close" : 'data-dismiss' => "modal"}
.diagRepeater
.modal-body
= simple_form_for Form.new, :url => {:controller => :form, :action => :modal_create} do |o|
=o.input :name, :label => 'Name', :required => true
=o.input :form_id, :as => :hidden
It is in this last file that I see the problem. If I comment out the simple_form_for and on, it will work great. If I leave it, it will break the rest of the form.

HTML not support nested form.
You can have several forms in a page but they should not be nested.
As you say: this work great in all browser for me it is miracle because 'You would even have problems making it work in different versions of the same browser' so avoid using that.
Webkit explain why HTML not supporting nested form
bool HTMLParser::formCreateErrorCheck(Token* t, RefPtr<Node>& result)
{
// Only create a new form if we're not already inside one.
// This is consistent with other browsers' behavior.
if (!m_currentFormElement) {
m_currentFormElement = new HTMLFormElement(formTag, m_document);
result = m_currentFormElement;
pCloserCreateErrorCheck(t, result);
}
return false;
}

Related

Displaying validation errors with Ruby

I'm having some trouble rendering validation messages using "remote => true"
I have a partially rendered form for saving an address
<%= render :partial => "registrations/address", :locals => {:address => #user.customer_addresses.build, :is_new => true, :checked => false} %>
In this form, the user clicks this button to create a new address
<%= link_to "Save Address", "javascript://", :remote => true, :data => "new", "data-target" => create_user_address_url, "data-method" => "Post" %>
I have the 'create_address' function set up in the controller (which returns the validation errors), as well as a create_address.js.erb file. However, it doesnt seem like the browser is executing anything in the js file.
It would be great to see the code of js.erb file
But I assume you have escape javascript issue.
Just use j in your render partial method. E.g.
<%= j render('partial_name') %>
You might have forgot to reload the partial which show the error message. After using remote => true you need to reload the partial so that the changes will reflect on that partial.

Undefined local variable in rails form

Edit:
It turns out, this was really an issue of syntax when using render for partials. It should be render partial:
I am following this blog post guide to implement the acts_as_commentable_with_threading gem.
http://twocentstudios.com/blog/2012/11/15/simple-ajax-comments-with-rails/
I have a character model with the following comment form partial in the show.html.haml view.
This line is giving me an undefined local variable or method for 'comment'
app/views/characters/show.html.haml
...
= render 'comments/form', :locals => { comment => #new_comment }
...
The hash inside the locals hash seemed off to me, so i changed the comment local variable to :comment. This worked fine, but I don't believe that is I am supposed to do.
When I do this, the form partial that is rendered also uses a comment local variable.
app/views/comments/_form.html.haml
.comment-form
= simple_form_for comment, :url => comment_path, :remote => true do |f|
= f.error_notification
= f.input :body, :input_html => { :rows => "3" }, :label => false
= f.input :commentable_type, :as => :hidden, :value => comment.commentable_type
= f.input :commentable_id, :as => :hidden, :value => comment.commentable_id
= f.error :base
= f.button :submit, :class => "btn btn-primary", :disable_with => "Submitting…"
Notice that the object passed into the simple_form_for method is also a local variable. This raised an error too, and i turned it into a symbol as well. Next, the comment.commentable_type raised an error, naturally, because comment was not defined. I cannot turn this into a hash because it is having a method call on it, right?
Whatever the answer is to the question is, it seems like I am going about this the wrong way. I shouldn't be turning things into symbols, when the problem is really that it isn't defined. Where should I define it? Where and how should I define it? I tried simply doing comment in the comments controller,
I am using rails 4.0.0, using simple form, and haml. Could it be a bad syntax for simple form?
EDIT: it was a second line rendering the comment partial that was raising the error. (everything being named comment was making it hard to tell where it was coming from.
= render 'comments/form', comment: #new_comment
= render 'comments/a_comment', collection: #comments, as: :comment
-# partial for a single comment.
%div.comment{ :id => "comment-#{comment.id}" }
%hr
= link_to "×", comment_path(comment), :method => :delete, :remote => true, :confirm => "Are you sure you want to remove this comment?", :disable_with => "×", :class => 'close'
%h4
= comment.user.username
%small= comment.updated_at
%p= comment.body
%h4
In your controller:
def show
#character = Character.find(params[:id])
#new_comment = #character.comments.build
end
Assuming there is a has_many relation between character and comment.
In your view:
render partial: 'comments/form', locals: { new_comment: #new_comment }
or
render 'comments/form', new_comment: #new_comment
In your partial:
= simple_form_for new_comment, remote: true do |f|

kaminari pagination ajax call renders to wrong controller

First we start off with conversations/index.html.haml to create a message
#new_message_conversation
.panel.panel-info
.panel-heading
%h4 Send a Bark!
.panel-footer(style="padding-top: 20px")
= simple_form_for :message, url: :messages, :remote => true do |f|
.form-group
= f.input :master_name, placeholder: 'Choose master...', label: false, :url => autocomplete_master_name_conversations_path, :as => :autocomplete, id_element: "#master_name_id", input_html: {class: "form-control"}
= f.input :recipient_id, as: "hidden", input_html: {id: "master_name_id"}
= f.input :body, label: false, as: "text", placeholder: 'Write message...', :input_html => { :rows => 5 }
= f.button :submit, 'Send', :class => "btn btn-lg btn-primary", :disable_with => "Sending..."
which then goes to the messages#create action which has
...
respond_to do |format|
format.js { render "create", locals: { conversation: #conversation, conversations: #conversations, receipts: #receipts }}
end
...
which sends the work to the conversations/create.js.erb file
$('#new_message_conversation').prop('disabled', true).html("<%= raw escape_javascript(render(:partial => 'conversations/show', locals: { conversation: conversation, receipts: receipts })) %>").hide().fadeIn('fast');
which adds the conversations/show partial, _show.html.haml which has
...
%ul.pager.pull-left(style= "padding-left: 10px")
%li#paginator_3= link_to_previous_page #receipts, "Newer", :remote => true, :param_name => 'page_2'
%li#paginator_4= link_to_next_page #receipts, "Older", :remote => true, :param_name => 'page_2'
...
everything works excepts now the pagination buttons don't work. and when I click a pagination button the server says
Rendered messages/index.js.erb
Why does a partial that's in views/conversations that has a remote ajax call render to a different controller (messages)? It should be rendering conversations/show.js.erb because the partial is conversations/_show.html.haml right?
here are my routes also
...
resources :conversations do
get :autocomplete_master_name, :on => :collection
end
resources :messages
...
Even though you're rendering views and partials from the conversations path, you never even touched the ConversationController.
You can render whatever views you want for the action you're executing. The only thing connecting the ConversationController with the views/conversation/file.html.erb and similar view files is a loose naming convention. When rendering say render 'index' from an action of the ConversationController, it just assumes by that convention you meant the views/conversation/index.html.erb file.
Your view or partial alone cannot reference the controller it would belong to (when going by the naming convention) because it is just used as a template by the render command in your action. The view doesn't care whether the controller behind it is the appropriate one. In this case, the render was originally executed in the MessagesController, so the view also just has a reference to that one.
To still have the links point to the correct controller, you need to specify the controller to be used for the url. Otherwise, it is assumed that you want to use the very same controller you used to render the page.
The culprit is probably somewhere in the link_to_previous_page and link_to_next_page helpers by kaminari. When using the full paginate helper, you can set the controller and action you want to use like this:
<%= paginate #users, :params => {:controller => 'foo', :action => 'bar'} %>
The documentation (here: https://github.com/amatsuda/kaminari) doesn't say whether this param is also possible with the other helpers, but the helper uses a simple link_to (see here: https://github.com/amatsuda/kaminari/blob/master/lib/kaminari/helpers/action_view_extension.rb), so you should be able to do something like this:
link_to_previous_page #receipts, "Newer", {:controller => 'foo', :action => 'bar', :remote => true, :param_name => 'page_2'}

Rails: How to render repetitive form block?

In order to not repeat myself, I would like to create a function that render a form block (text field or text area) in a specific way. I want a result like this one (using Haml, and twitter-bootstrap):
.form-block.input-prepend
%span.add-on>
%i.icon.icon-home
= f.text_field :name, :value => #store.name, :placeholder => 'Company Name'
To do that, I created a file views/layouts/_form-block.html.haml where I inserted the following code:
.form-block.input-prepend
%span.add-on>
%i{ :class => "icon icon-#{icon}" }
= yield
And I call the block in my view using:
- render :template => 'layouts/_form-block', :locals => { :icon => 'home' } do
= f.text_field :name, :value => #store.name, :placeholder => 'Company Name'
But It doesn't work. I have the following error 'nil' is not an ActiveModel-compatible object that returns a valid partial path.
Do you have any idea? Is this the best way to do?
Thanks in advance.
If you want to use = yield to pass a block, you need to render as a layout. Use render :layout => instead of render :template =>.

Rails route for button

I'm a rails newbie and a question on routes is confusing me.
On one of my pages, I have a form. In that form I allow the user to fill in some needed information and press a "submit" button.
I get:
No route matches {:action=>"inventory_test", :controller=>"test_types"}
I do have an action in the test_type controller for "inventory_test".
My confusion is that routes seem to be defined according to the REST model, such as /Users/edit/1. That's fine, but how does one create routes for things like buttons?
I may be naive, but it seems like if I tried to setup a route in the form:
match 'some/url' => 'controller#action'
then I'm essentially defining the action for the entire page. How do I define actions for elements on the page?
When this button is clicked, I want the action in the controller called. I'm looking for:
match "submit_button" => 'test_types#inventory_test'
I realize I'm likely misunderstanding the paradigm, so any education is greatly appreciated.
Code:
(Note that I haven't tested the form code yet, but hopefully you get the idea)
index.html.haml
%div
%table
%caption
Inventory Tests
%form
Inventory Run: %input {:type => 'text', :name=>'inventory_run'}
Inventory Class: %input {:type => 'text', :name=>'inventory_class'}
=button_to "Run Inventory Test", :action => 'inventory_test';
If you are submitting a normal form then this should help
The route match '/url' => "test_types#inventory_test" should work fine.
<%= form_for(#user, :url => "/url") do |f| %>
"Put your form code here"
<%= f.submit "Submit" %>
<% end %>
Revert back if any queries .
Edited as per code posted
%form{ :action => "inventory_test", :method => "post"}
%label{:for => "inventory_run"} Inventory Run:
%input{:type => "text", :name => "inventory_run"}
%label{:for => "inventory_class"} Inventory Class:
%input{:type => "text", :name => "inventory_class"}
%input{:type => "submit", :value => "Submit"}
Just check, it should work for you but i have not tried with it

Resources