How to render each views without reloading in rails? - ruby-on-rails

I have a problematic to render my views in my rails app.
I try to create a home page who load each tools of my app (5 - 6 different) but I want to allow users to call them one by one and without reloading the page (like some saas apps).
I tried with a welcome/index.html.erb page that render each views with ajax:
<button class="button1"></button>
<button class="button2"></button>
<button class="button3"></button>
<%= render "tools1/index %>
<%= render "tools2/index %>
<%= render "tools3/index %>
...
How could I do to show only tools 1 if the user click on button1, and then hide tools1 and show tools2 when the user click on button2, etc. ?
Another question, is it an efficient way to do that ?
Edit:
My fault, it wasn't clear. The point is that I don't want to render each page at the beginning, the perfect stuff will be to load (not just show) them page by page, just when the user call them
Thanks

A quick AJAX loader example
Add some links/buttons to your HTML:
<a class="ajax-load" href="/url1">Page 1</a>
<a class="ajax-load" href="/url2">Page 2</a>
<a class="ajax-load" href="/url3">Page 3</a>
<div class="ajax-content"></div>
Add this jQuery code:
$(document).ready(function(){
$('.ajax-load').on('click', function(e){
e.preventDefault();
$('.ajax-content').load($(this).attr('href'));
});
});
Now, when users click on any link, the content will be AJAX loaded.
Previous answer
Since you are rendering your pages in your view, you don't need to ajax load them again. I would suggest using some jQuery plugins to do this for you.
For example: tabs or accordion.

Related

Ruby on Rails - Show the same modal with different content

I have a home page with a list of software in a table.
With this link I open my softwares pages in modals:
<% = link_to software_path (software), remote: true do %> ... <% end%>
I created a script allowing me to open my modals when I click on td with class .clickable and not open modals when I click on a td with class .no-click.
$(".clickable").click(function(e) {
if (!$(e.target).hasClass('no-click')) {
$('#software-modal').modal('show');
}
});
structure :
_software.html.erb open _software_modal.html.erb
Problem:
When I try to open my modals via the script, it's always the same modal that opens. That is, the modal of software 1 opens when I click on software 2, software 3, ... but no problem when I just use the link.
So I have a problem with id or something like that in my script ...
Can you help me ?
EDIT 1: With the response of VAD I tried to search the id with data-id.
_software.html.erb
<tr class="clickable" data-id="<%= software.id %>">
...
</tr>
<div id='software-content'></div>
_software_modal.html.erb
<div id="software-modal" class="modal fade" role="dialog">
...
</div>
show.js.erb
$('#software-content').html("<%= j render 'software_modal', software: #software %>");
$('#software-modal').modal('show');
this show.js.erb allows me to open my modals via example links:
<%= link_to software.name, software_path(software), remote: true,class:"no-click" %>
but not via a clickable table.
So I added a script in _software.html.erb that makes my table clickable:
$(".clickable[data-id]").click(function(e) {
if (!$(e.target).hasClass('no-click')) {
window.location = '/softwares/' + $(this).attr('data-id');
}
});
I also tried with data-link, ... is there a way to open this window.location in a modal (like the link)? I searched for several hours yesterday but I did not find anything ..
EDIT 2
following the response of #VAD with render layout: false, we can put:
class ApplicationController < ActionController::Base
   layout proc{|c| c.request.xhr? ? false : "application" }
end
which allows to have a false render for the js and true render for html. And so to keep my html pages with my starting layout.
Thx #dogenpunk
Render without layout when format is JS (needs drying)
You need to have different modals for every place you want to show the modal from. Like for software1 you need to show the modal with content relative to this particular object. For software2 you'll need to show the same model but with a brand new content relative to software2
Another option (and the better one) is that you may have one single modal for every Software object but by some event (for example actually showing the modal) you'll update the modal content with the data specific for this particular Software object. You may use some controller action for that
Additional
Try to pass software id as data parameters in your clickable elements and then to update your modal content with ajax and like that
<div class = 'clickable' data-id = "#{software.id}">
</div>
$(".clickable").click(function(e) {
if (!$(e.target).hasClass('no-click')) {
$.get('/softwares/' + $(this).attr('data_id'), function(data) {
$('#software-modal body').html(data);
});
$('#software-modal').modal('show');
}
});
Of course I can't give precise code so you'll need to adjust it according to you current setup
Update
The idea is that you have show action in softwares_controller.rb which eventually renders the content for your modals:
def show
// some code you need
render layout: false
end
It will render show.html.erb view. In that view you should keep the html for your modal content. Notice that the action will render that view without layout. You need this because you will soon take this html and will put it into the modal, so you don't need any extra html like the layout.
So, you have an action which render the modal content for every software object by its id.
Now you need to put it into the modal.
You have clickable elements in your markup. You attach correspondent software ids to them as data-id. Then in your jquery code you use these ids to construct a url like this:
'/softwares/' + $(this).attr('data_id')
This url will lead to your show action in softwares_controller.rb. So by clicking on one of clickable elements you take the id, generate the url with it, send request to the url, get the response (the modal content) and then put it into the modal like this:
$.get('/softwares/' + $(this).attr('data_id'), function(data) {
$('#software-modal body').html(data);
});
Then you show the modal with already updated content:
$('#software-modal').modal('show');

Loader image for rails controller action

Hi In my rails application on one page I have links which links to another page which will call some APIs, so that page loads slowly. I need some indication till the page renders, how to accomplish this? I have searched most of them says solution for AJAX request but here its not a ajax request.....
Add in your application.js
$(document).ajaxStart(function(){
showloader()
});
$(document).ajaxStop(function(){
hideloader()
});
function showloader(){
$(".main-loader").show()
}
function hideloader(){
$(".main-loader").hide()
}
Add in your application.html.erb
<div class="main-loader" style="display: none;">
<div class="loader-div"> <%= image_tag "loader.gif" %> </div>
</div>
And Also Add loader image in your assets images folder

Using devise gem, how does it prefill form values in the edit form and how can this be replicated elsewhere?

I am attempting to place the sign in, sign up and edit forms (from devise) into Bootstrap modals using partials. I have successfully done this by creating partials for the forms (wrapped in the modal code) and rendering them in application.html.erb as follows:
<%= render 'articles/sign_up_modal' %>
<%= render 'articles/sign_in_modal' %>
<%= render 'articles/edit_profile_modal' %>
At the top of application.html.erb I have:
<script type="text/javascript"> $(function () { $("#sign_up").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#sign_in").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#edit_profile").modal({show:false });</script>
Where "sign_up", "sign_in" and "edit_profile" represent the id's of the modals from the partials. The modal is then displayed by clicking a button in the _header.html.erb partial:
<%= link_to '<button type="button" class="btn btn-primary">Edit Profile</button>'.html_safe, "#edit_profile", "data-toggle" => "modal" %>
Everything works great except the Edit Profile modal form does not prefill the form with the appropriate values unless I am also on the edit page when I click the button to display the modal. How can I get the Edit Profile modal form to prefill the users data no matter which page they are on in the background?
Does this make sense? Please tell me how I might clarify my question. Thanks!
The answer was provided to me by u/alec5216 on reddit.
He said:
Take a look at the devise source.
https://github.com/plataformatec/devise/blob/master/app/views/devise/registrations/edit.html.erb
You'll see the form is bound to the "resource" variable which is going to be an instance of a user model. I bet if you use current_user in the partial instead of resource you'll have the desired effect.
This worked. See HERE for the full conversation.
In this case you will probably have to make an AJAX call to fetch the required data.
The data itself can either be JSON (for client-side rendering) or the complete html form rendered with the layout: false option. I usually go for the former because it is faster and easier to implement, unless your project is a single-page js application.
You can find more information on bootstrap ajax modals here on StackOverflow.

how to close view template in Rails 3

I have opened the view template as popup by using the following code:
<%= link_to 'New User', "/users/new", :method => :get, :target => "_blank" %>
controller code:
def new
render :layout => false
end
the new.html.erb is having few textboxes and buttons as Save and Cancel
My problem is how can i close the popup upon clicking Save or Cancel button?
Thank u,
Sudhir C.N.
This a more a javascript question rather than one specific to Rails.
Your Cancel button is easy enough, something like:
<html>
<script>
function CloseWindow() {
ww = window.open(window.location, "_self");
ww.close();
}
</script>
<button type="button" onclick="CloseWindow();">Cancel</button>
</html>
(stolen from http://snippets.dzone.com/posts/show/267)
Your submit button shouldn't change. It will need to POST to your controller as normal. The successful response rendered by the controller should display a "Success" message in the flash and could then close the window automatically after, say, three seconds:
<script>
setTimeout( function() { CloseWindow(); }, 3000);
</script>
This is a pretty simple solution. Maybe consider investigating some popup libraries for either prototype or jquery (depending on the library you're using). Not sure whether modern popup blockers render these D.O.A. though. Your target="_blank" approach should play nice with popup blockers.
Edit: if you're using jquery maybe consider something like the modal dialog: http://jqueryui.com/demos/dialog/#modal-form
You will need to do it with javascript. After the user saves you can respond with another view that sends this:
<script type="text/javascript">
window.close();
</script>

Rails 3 - Simplemodal pop up with forms

I am trying to use Simplemodal as a pop up box on an index page and put a form to add a new user inside it. It's not working, says there is an undefined method. How do I make this work? Does it have to do with :remote?
EDIT - Here's some code to hopefully explain a little better - from index.html.erb
<div id='basic-modal'>
<input type='button' name='basic' value='Demo' class='basic'/>
</div>
<!-- modal content -->
<div id="basic-modal-content">
<%= render 'form' %>
</div>
My form is the standard scaffold form, my Client model has a place to add some basic information about a client. My controller is the standard controller that is generated with scaffold, and my application.html.erb adds the required .js files. When I take the
<%= render 'form' %>
out and put in just plain text, it works just fine. Does that help?
Although I haven't found the answer to using simplemodal for a modal box, I found this tutorial at Nettus which uses modalbox and facebox:
http://net.tutsplus.com/tutorials/ruby/how-to-build-an-unobtrusive-login-system-in-rails/
With a few changes for rails 3, this helped me put a form inside a modal box with no problems.

Resources