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
Related
So..I’m trying to understand usage of modals in Rails and looking for a few pointers.
I have a list of items at at category/1 which are being displayed in a loop. I have a modal which I’m rendering at the bottom of the page with <%= render "category/update_item_modal" %>
There’s already a form setup for updating params of each item, but I’m trying to get a modal pop up to specifically just update the title. The modal popup works, and so far I have the following for the button which opens the modal:-
<button class="btn btn-primary btn-sm">Edit Title</button>
And the modal itself:-
<div class="modal fade" id="updateItemModal-<%= item.id %>" tabindex="-1" role="dialog" aria-labelledby="updateItemModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="updateItemModalLabel">Change Item</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- UPDATE TITLE HERE? -->
</div>
</div>
</div>
</div>
This gives me the error of undefined local variable "id" from the modal id for obvious reasons, and this is where my understanding hits a wall. How do I pass the data from a loop iteration into my modal?
End goal is to have an editable textarea field with the existing title in it, and a submit button which will post the edit.
Provided you have defined #item in your controller:
<%= render "category/update_item_modal", locals: item: #item %>
Then you have access to item in your partial. One more thing you can do to avoid that error is to use the safe operation operator item&.id. More on the safe navigation operator here: https://bugs.ruby-lang.org/issues/11537
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')
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.
I'm trying to figure out how to manage the ability to call my controller from a link and return the data after all process is completed, while at the same time displaying a modal with that data returned. Here's my logic that I have yet to figure out and hope someone can help;
I've tried the following with no success;
#HTML
<%= link_to "#WidgetGenModal", :data => {:toggle => "modal"}, :action => 'gen_key', :class => 'gen-widget pull-right' do %><i class="fa fa-slideshare fa-1x"></i><% end %>
#CONTROLLER (Widget controller)
protected
def generate_token
user = current_user
self.token = loop do
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless user.widget.exists?(token: random_token)
end
end
#MODAL (Bootstrap)
<div class="modal fade" id="WidgetGenModal" tabindex="-1" role="dialog" aria-labelledby="widgetGenModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="widgetGenModal"><div class="btn btn-danger btn-xs">NEW</div> Share Your Category</h3>
<p>We've made it easier for you to share everything you store / save within your categories. Simply copy the specially generated code, paste it some where on your website or share the link with someone to let them see what you've saved.</p>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<div id="test"></div>
<%= f.hidden_field :color, value: '' %><div id="output"></div>
<div class="clearfix visible-xs"></div>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<!-- /.modal -->
I guess I'm having a hard time moving the token into my Modal as that what I'm trying to work out here. Suggestions?
One way to do that is to render empty modal in your view and give an id to its body. After sending an ajax request to the action render .js file that injects the new data to the body of the modal and use
$("#Modal_ID").modal("toggle")
ex ::
in your view ::
<%= link_to "NAME OF LINK", PATH_TO_YOUR_ACTION, :"data-toggle"=>"modal", :"data-target"=>"#WidgetGenModal", class: "company-name-link", remote: true%>
<%= render "YOUR_EMPTY_MODAL_PARTIAL"%>
in your empty modal partial
<div class="modal fade" id="WidgetGenModal" tabindex="-1" role="dialog" aria-labelledby="widgetGenModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="widgetGenModal"><div class="btn btn-danger btn-xs">NEW</div> Share Your Category</h3>
<p>We've made it easier for you to share everything you store / save within your categories. Simply copy the specially generated code, paste it some where on your website or share the link with someone to let them see what you've saved.</p>
</div>
<div class="modal-body" id="WidgetGenModalBody">
</div>
<div class="modal-footer">
<div id="test"></div>
<%= f.hidden_field :color, value: '' %><div id="output"></div>
<div class="clearfix visible-xs"></div>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div>
<!-- /.modal -->
Please check your logic for f.hidden_field this is not right.
in your action ::
def your_action
// whatever
format.js
end
in your_action.js file in views
$("WidgetGenModalBody").html('<%= YOUR DATA RETURNED OR PARTIAL CONTAING THE DATA %>')
$("WidgetGenModal").modal("toggle")
I am having some difficulties getting the Kaminari gem to work with my Bootstrap modal. I know that it needs to work primarily with Ajax, but I'm not quite sure what to do on this one.
Specifically, I have over 800 images that are supposed to load in the Modal. But, right now, all those images are loading at once, causing a long loading time.
Here's what I currently have:
new.html.erb
# basic html items
<%= render "image_modal" %>
_image_modal.html.erb
<div class="modal fade" id="choosePicture" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Choose Your Image</h4>
</div>
<div class="modal-body">
<div class="row">
<% #images_by_filename.each do |image| %>
<div class=" col-xs-3">
<div class="thumbnail">
<%= image_tag image.picture(:square), :title => image.name, :id => image.id, :image_url => image.picture(:thumb), :class => "list_thumb image-select style_image" %>
</div>
</div>
<% end %>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
</div><!-- /.modal-content -->
images_controller.rb
class ImagesController < ApplicationController
def new
#template = Template.new
#groups = Group.all
#images = #images_by_filename
#template.template_assignments.build
end
end
How could I incorporate Kaminari to work within this modal, separately? When I try to implement the pagination, it ends up refreshing the entire page, as opposed to just within the modal.
Any help on this would be great!
Some code is missing in controller and view files.
images_controller.rb
#images = #images_by_filename.page(params[:page]).per(number_of_records_per_page)
_image_modal.html.erb
= paginate #images
You can refer http://railscasts.com/episodes/254-pagination-with-kaminari for more help.
Hope this will help you.