In my Rails 4 app, I am trying to display some views as modals (with Bootstrap modal), instead of the regular .html.erb views.
For instance, I have a calendar model, with a custom analysis action in the controller:
def analysis
#calendar = Calendar.find(params[:id])
respond_to do |format|
format.js
end
end
Following what is explained in this tutorial and that other tutorial, I am trying to create the following files:
# _dialog.html.erb
<div class="modal fade" id="dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close"
data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span></button>
<h3 class="modal-title"></h3>
</div>
<div class="modal-body">
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
# _analysis.html.erb
<p><%= #calendar.name %> Analysis</p>
# analysis.js.erb
// Add the dialog title
$('#dialog h3').html("Calendar Analysis");
// Render calendar analysis
$('.modal-body').html('<%= j render(:partial => 'calendars/analysis') %>');
// Show the dynamic dialog
$('#dialog').modal("show");
// Set focus to the first element
$('#dialog').on('shown.bs.modal', function () {
$('.first_input').focus()
})
Last but not least, I call the modal from a _heading.html.erb partial, rendered inside the calendar show.html.erb view, with the <%= render 'analysis' %> helper and the following link:
<%= link_to '<i class="glyphicon glyphicon-dashboard"></i>'.html_safe, calendar_analysis_path, :remote => true, 'data-toggle' => "modal", 'data-target' => '#modal-window' %>
When I launch my app, I then get the following error:
undefined method `render' for #<#<Class:0x007fee248d8118>:0x007fee23577ce0>
—————
UPDATE: I have tried different ways to render the partial:
As recommended here, I tried both escape_javascript render and j render.
As recommended there, I have also tried render_to_string instead of just render.
As recommended in that other question, I even tried different ways to call the partial, both with render(:partial => 'calendars/analysis') and (render 'calendars/analysis').
But none of these solutions worked.
—————
I have done quite a lot of research on that topic and I have to say that I am confused now.
While both tutorials mentioned above recommend this approach, other sources, including this one, point out that you cannot render a partial from assets in Rails.
Therefore:
What is wrong with my current code?
Does the approach I am trying to use make sense at all, and if not, what shoud I do instead?
The code under app/assets can not call render. Actually it can not call almost anything except a very few methods.
Move it somewhere to app/views/somethings/analysis.js.erb
Where somethings is the name of your controller in plural form, so just put it near the _analysis.html.erb.
Related
Say I have a Scaffolded Post with just one field, body.I would like to render the show page for any post by clicking show only instead of loading a separate show page, It loads it inside a modal. Kinda like twitter does
I assume you are using Bootstrap and you would like to use a modal. You will have the list view have the modal with some links.
Now to get the data, we can do it either on page load (lets say data attributes), or on demand through XHR.
I like to get things on demand... so lets make a modal and some links.
<% #posts.each do |post| %>
<%= link_to post.title, post_path(post), remote: true, data: { method: 'get' } %>
<% end %>
<div class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">Modal title</h4>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
Then in the controller we need to make it fire...
class PostsController < ApplicationController
def show
#post = Post.find(params[:id])
respond_to do |format|
format.js
end
end
end
In the view show.js.erb we will do some thing like this.
$('h4.modal-title').html("<%= #post.title %>");
$('.modal-body p').html("<%= #post.body %>");
$('.modal').modal();
Let me know if it has bugs, I just wrote it out of my head and the modal code came right from Bootstrap with no editing. You will probably have to refactor them to make sense.
You cannot render the entire show page directly, but you can do this with a partial. I would recommend creating a partial that encapsulates all of the view information that is common to your show page and your modal. You can then reference that partial in both your show page and your modal reducing the amount of duplicated code.
Partials are normal view files with an underscore as the first character of the file name. For example: _post.html.erb.
You render the partial inside other views with the render command:
#show.html.erb
<%= render 'post' %>
I would also recommend the Rails Guide on Layouts and Rendering
I am using Rails 5 on my project.
I have a home_controller with index action. In the index view i render a partial(_stories.html.erb) but the code after partial doesn't display, seems some times if i get back from some page it shows up.
What's the issue here?
And if i want to make index.html.erb (home page) with some layout parts, what's the correct way? Is render different partials in `index.html.erb'?
index.html.erb
<%= render :partial => 'stories/stories' %>
<!-- The code below doesn't show up -->
<button id="myBtn">Open Modal</button>
<div id="myModal" class="modal">
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>
I solved the issue, I redirect to wrong path so the after code didn't show up!
I have a form in my view, and upon submission, my controller validates the fields and returns a list of errors in #errors, if any.
Now, I want to display these errors in a modal.
Here's what I have in my View:
!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<%= render 'shared/errors' %>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
I want to display this modal on page load, if and only if #errors exists.
It looks like coffeescripts don't have access to variables passed by the controller.
I came across a few similar questions, but none of them seem to solve my problem.
you can do this with the help of gon gem.
Add "gem 'gon'" to your Gemfile.
run bundle install.
set value in controller like this: gon.form_errors = true if #errors.present?
Add this line in application layout in head section before all javascript include tags:- For rails 4: <%= Gon::Base.render_data %> and for rails 3 <%= include_gon %>
Now you can access this variable in your coffee file like this: gon.variable_name and use it like this:
if gon.form_errors
$('#your-modal-id').modal('show')
There are two modals being used in the Rails app.
One modal is used for editing (#editModal)
The other one is for displaying text (#textModal)
link_to for both the modals are:
<%= link_to edit_user_path(user), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#editModal', 'data-backdrop' => 'static', :class => "icon-edit" } do %>
Edit
<% end %>
<%= link_to display_path(data), {:remote => true, 'data-toggle' => "modal", 'data-target' => '#textModal', 'data-backdrop' => 'static', :class => "icon-edit" } do %>
Display
<% end %>
_editModal.html.erb
<div id="editModal" class="modal fade edit-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
</div>
<div class="modal-body">
<%= render 'shared/ajax_load' %>
</div>
</div>
</div>
</div>
_textModal.html.erb
<div id="textModal" class="modal fade edit-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
</div>
<div class="modal-body msg-body">
<%= render 'shared/ajax_load' %>
</div>
</div>
</div>
</div>
The problem is when any of the link is clicked one modal is displayed, but the content is loaded into both the modals.
Am I doing anything wrong or that's how it works??
Well... Yes and Yes.
You are doing something wrong... and that's how it works. :)
The only difference I can see in your two modals is the id. Every other thing is the same... even up to the partial being rendered: <%= render 'shared/ajax_load' %>
What this means is that whenever you click any of the buttons, the partial 'shared/ajax_load' gets populated and will remain populated until you refresh the page.
Fix:
Two things I can readily suggest here:
1) You can decide to have separate partials rendered for the two modals
2) You can decide to use JS to populate the modal(If you want to use the single partial): then you will have the control to clear off the content of the partial before populating it and rendering into the respective modals
Hope I've been able to explain and hope you understand this.
I have a Rails view with two icons. Each icon should open a different modal (using a partial).
The issue is that both icons are opening the same modal (the first one).
Here is the code to display the modals:
<a data-toggle="modal" href="#workorder-<%= workorder.id %>">
<i class="icon-list"></i><%= workorder.wologs.count %>
<%= render :partial => "wologs/history", locals: {workorder: workorder} %>
</a>
<a data-toggle="modal" href="#workorder-<%= workorder.id %>">
<i class="icon-ok-sign"></i><%= workorder.tasks.count %></a>
<%= render :partial => "tasks/taskslist", locals: {workorder: workorder} %>
</a>
Thanks for the help!
As MrYoshiji already mentioned the reason is two links point to same id, so same modal launched.
I would like to add that it's also incorrect to put the modal body inside link, if the partial is modal body.
According to Bootstrap example:
Launch demo modal
<!-- Modal -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
</div>
The link and modal are two totally different divs.
So the fix is:
Launch partial in different div and assign different ids to them.