Rails form above Twitter Bootstrap modal - ruby-on-rails

I'm trying to create a newsletter subscription from scratch using rails 4 and Twitter Bootstrap 3 modal.
I created a Subscriber model and subscribers controller which contains a 'create' method.
The button which openes the modal has to appear anytime, so I included it in the navbar that is placed in the application.html.erb layout view file.
This is the code I used for the modal: (in views/layout/application.html.erb)
<div class="modal fade" id="myModal" 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"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Newsletter Subscriptions</h4>
</div>
<% form_tag(controller: 'subscribers', action: 'create') do %>
<div class="modal-body">
<p><%= text_field_tag :email, params[:email] placeholder: "Enter your email address" %></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<p><%= submit_tag "Subscribe", class: "btn btn-primary" %></p>
</div>
<% end %>
</div>
</div>
</div>
For some reason it won't show anything in the modal except the title.
Where am I going wrong?

You just need to use <%= form_tag instead of <% form_tag.
In previous versions of Rails, <% form_tag was used I think, but since form_tag is outputting html, it should be used with <%= %>.

Related

Rails way to pass data from 'for' to modal

I'm trying to pass a variable being defined in an 'for' loop down to a modal button. Currently I have the modal block being rendered in the for as a quick win but I find it redundant to be making the entire modal block in the DOM for nothing.
<h3>User</h3>
<p>Name: <%= #user.name if #user.name %></p>
<p>Email: <%= #user.email if #user.email %></p>
<% #user.authentications.each do |i| %>
<%= i.provider.titleize %><br>
<%= i.created_at.strftime("%m/%d/%Y") %><br>
<button type="button" class="btn btn-info btn-lg modal-btn-swap" data-toggle="modal" data-target="#myModal" data=<%= i.id %>>Delete Auth</button>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Remove authorization</h4>
</div>
<div class="modal-body">
<p>Some text
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<%= button_to 'Delete Auth', deauth_url(i.id) %>
<button type="button" class="btn btn-default"></button>
</div>
</div>
</div>
</div>
<% end %>
The concept is to just get a modal popup to give legal information prior to completing the transaction.
I'm thinking I'll need ot use jQuery to swap the href for the link when I click the 1st Delete Auth button.
Input?
If you create the modal once, you will have to write some javascript in the button click handler to populate the modal's attributes with the data you want each time you click, rather than hard coding it into each copy of the modal as you are doing now.
The ruby code would generate the modal -- you would have to leave the button_to('Delete Auth') without a target. Then you can copy the values from the data attribute to the modal when you click the button.

How to display different posts using Modals

I'm new to RoR and I've encountered a problem recently as I am trying to display different posts in different modals. To contextualize I have a Home page on which is displayed every post. Every post contains an author, a content, a like button and a comment button. I want the comment button to open a modal containing again the author's name, the content and an area to comment the post. The problem is that every modal that I click on contains the same author and the same content even if the comment button I clicked on is from a different post. To be precise the content displayed in the Modal is from the most recently posted post. Tell me if you need something in particular and I will be happy to edit this post with the code you'll ask me.
Displaying the posts:
<% #posts.each do |post| %>
<div class="media">
<a class="media-left" href="#">
<div class='circle-icon'>
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
</div>
</a>
<div class="media-body">
<h2 class="media-heading"><%= post.user.first_name %> <%= post.user.last_name %></h2>
<h4><%= post.content %> </h4>
<br>Submitted <%= time_ago_in_words (post.created_at) %> ago<br>
<%= button_to like_post_path(post), method: :put do %>Like<%= post.get_upvotes.size %>
<% end %>
<span class="glyphicon glyphicon-comment"></span> Comment
And here is my Modal:
<!-- Modal -->
<div class="modal fade .local-modal" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<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" id="myModalLabel"><%= post.user.first_name %> <%= post.user.last_name %></h4>
</div>
<div class="modal-body">
<p><%= post.content %> </p>
<hr>
<fieldset class="form-group">
<label for="exampleTextarea">Write your comment:</label>
<textarea class="form-control" id="exampleTextarea" rows="3"> </textarea>
</fieldset>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" >Like</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Comment</button>
</div>
</div>
</div>
</div>
Here is my JS Script:
<script>
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
$('[data-toggle="popover"]').popover({ html : true});
});
$('#popover').popover({
html : true,
title: function() {
return $("#popover-head").html();
},
content: function() {
return $("#popover-content").html();
}
});
</script>

Sidebar and rendering partial, trying to run a todo app on sidebar

I am new to ruby on rails, I have been recommended to using a sidebar so that on most pages it will show what I want. I currently have an application on its own page called Todo List. It simply let you create a task and displays the tasks. It runs on its own page. Now I want to move that app and let it function in my sidebar. I have implemented my sidebar as follow.
/views/layouts/application (in body)
<%= yield :sidebar %>
/views/myapp1/index
<% content_for(:sidebar) do %>
<% render :partial => "layouts/sidebar" %>
<% end %>
/views/layouts/_sidebar
<% if logged_in? %>
<div id="mySidenav" class="sidenav">
<div class="row", id="container_todo_lists">
<%= render #todo_lists %>
</div>
<div class="links" data-toggle="modal" data-target="#mynewtodo_list">
<%= link_to('New Todo List', 'javascript:;', :id => :random) %>
</div>
×
</div>
<span style="font-size:30px;cursor:pointer" onclick="openNav()">☰ Todo List</span>
<script>
function openNav() {document.getElementById("mySidenav").style.width = "250px";}
function closeNav() {document.getElementById("mySidenav").style.width = "0";}
</script>
<% end %>
<!-- Modal create action -->
<%= form_for(#todo_list, remote: true) do |f| %>
<div class="modal fade" id="mynewtodo_list" 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-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Todo</h4>
</div>
<div class="modal-body">
<div class="field">
<%= f.label :title %><br>
<%= f.text_area :title, class: "form-control todo_list_title" %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description, class: "form-control todo_list_content" %>
</div>
</div>
<div class="modal-footer">
<%= submit_tag "Create", class: "btn btn-primary" %>
<button type="button" class="btn btn-default" data-dismiss="modal" id="mynewtodo_listclose">Close</button>
</div>
</div>
</div>
</div>
<% end %>
<!-- Modal -->
I get this error
'nil' is not an ActiveModel-compatible object. It must implement :to_partial_path.
I think I know part of the problem is my
#todo_lists
Because I tried to called the sidebar on my todo_list page and it works, but the sidebar messed up my original application so that when I press edit and show it would turn the screen grey. Any suggestion is greatly appreciated. Thanks in advance.
/views/todo_lists/_todo_list.html.erb
<div class="text-center" id="todo_list_<%= todo_list.id %>">
<h3 class="panel-title"><%= todo_list.title %>
<sup style="color: #3BB2D6; position: absolute; top: 5px; right: 15px; text-align:right;">
(<%= time_ago_in_words(todo_list.created_at) %>)
</sup>
</h3>
<p><%= todo_list.description %></p>
<div class="row" role="group">
<div class="links1" data-toggle="modal" data-target="#myupdatetodo_list_<%= todo_list.id %>">
<%= link_to('Edit', 'javascript:;', :id => :random) %>
</div>
<div class="links1" data-toggle="modal" data-target="#myitemtodo_list_<%= todo_list.id %>">
<%= link_to('Show', 'javascript:;', :id => :random) %>
</div>
<div class="links1">
<%= link_to 'Destroy', todo_list, method: :delete, remote: true %>
</div>
</div>
<!-- Modal - update posts -->
<%= form_for(todo_list, :method => :put, remote: true) do |f| %>
<div class="modal fade" id="myupdatetodo_list_<%= todo_list.id %>" 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-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Edit</h4>
</div>
<div class="modal-body">
<div class="field">
<%= f.label :title %><br>
<%= f.text_area :title, class: "form-control" %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description, class: "form-control" %>
</div>
</div>
<div class="modal-footer">
<button type="button" id="myupdatebutton_<%= todo_list.id %>" class="btn btn-default" data-dismiss="modal">Close</button>
<%= submit_tag "Update", class: "btn btn-primary" %>
</div>
</div>
</div>
</div>
<% end %>
<!-- Modal -->
<!-- Modal - item posts -->
<%= form_for(todo_list, :method => :put, remote: true) do |f| %>
<div class="modal fade" id="myitemtodo_list_<%= todo_list.id %>" 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-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Items</h4>
</div>
<div class="modal-body">
<h3><%= todo_list.title %></h3>
<p><%= todo_list.description %></p>
</div>
<div class="modal-footer">
<button type="button" id="myitembutton_<%= todo_list.id %>" class="btn btn-default" data-dismiss="modal">Close</button>
<%= submit_tag "Add Item", class: "btn btn-primary" %>
</div>
</div>
</div>
</div>
<% end %>
<!-- Modal -->
In your case, that is because the #todo_lists isn't being set, I'm sure if you go back to the previous url that was rendering the view, the sidebar would show.
A way to resolve is to ensure it's set on every page as such:
class ApplicationController
before_action :set_to_do_lists
def set_to_do_lists
#todo_lists ||= TodoList.all #assign this to what's in your todo_lists_path
end
end
With that I guess your app should be fixed

bootstrap modal does not show,only showing backdrop

I have posted this before but no one has reply me on my problem. However, after trying for few days. I encountered something funny.
My View Code
<% provide(:title, "Log in") %>
<div class="center jumbotron">
<h1> Kaching </h1>
<div class = "row" >
<div class="col-md-6 col-md-offset-3">
<%= form_for(:session, url: login_path) do |f| %>
<%= f.label :logID, "Log ID" %>
<%= f.text_field :logID %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Log In", class:"btn btn-primary" %>
<% end %>
</div>
</div>
</div>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(window).load(function(){
$('#myModal').modal('show');
});
</script>
When i include the code, the modal box will appear when i load the page. However, my modal still will not appear when i press the button. I do not understand why. It will only work when i include bootstrap.js in my /assets/javascripts folder. However, this affects my tab that i implement on my other page. I try loading just the bootstrap-modal.js file, but it did not work also. Please guide me on this.
Thanks

how to not improve this code to not repeat the twitter bootstrap modal?

I have a Project that have many Pictures. I am using the first picture as a link to call a twitter bootstrap modal, where some information will be displayed as well as the link for the project`s page.
<!-- Modal -->
<div id="<%= project.id %>" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3><%= project.title %> <small><%= project.sub_title %></small></h3>
</div>
<div class="modal-body">
<p><%= ActionView::Base.full_sanitizer.sanitize (project.description) %></p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<%= link_to 'More Details', project_path(project), class: 'btn btn-primary' %>
</div>
</div>
In order to get the modal working for each project, I have added the project.id to the Modal id. So, I am actually creating many modals, one for each project.
<% #projects.each do |project| %>
<%= link_to (image_tag project.pictures.first.url), "##{project.id}", class: 'btn', role: 'button', data: { toggle: 'modal' } %>
<%= render 'projects/modal', project: project %>
<% end %>
Well, everything is working fine, but I don't like it! It will became a loading problem if I have many projects.
So, I would like to find a way to not load all modals. I would like to have one modal template that is populated by the project information.
Any idea on how to improve it?
NOTE: I don't have rails set up at the moment, so can't test this directly, but should work:
Put the following generic modal code into the modal partial:
<div id="genericModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3></h3>
</div>
<div class="modal-body">
<p></p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<%= link_to 'More Details', nil, class: 'btn btn-primary' %>
</div>
</div>
Include the following at the top of your view:
<script>
function populateModal(projectId) {
$(".modal-header").find("h3").html($(projectId).find("#p_title").html());
$(".modal-body").find("p").html($(projectId).find("#p_desc").html());
$(".modal-footer").find("a").attr("href", $(projectId).find("#p_link > a").attr("href"));
$("#genericModal").modal('show');
}
</script>
Then further down in your view, you can do something like this:
<%= render 'projects/modal' %>
<% #projects.each do |project| %>
<%= link_to (image_tag project.pictures.first.url), html => {:onclick => "populateModal('##{project.id}')", :class => 'btn', :role => 'button'} %>
<div id="#{project.id}" class="hide">
<span id="p_title"><%= project.title %> <small><%= project.sub_title %><small></span>
<span id="p_desc"><%= ActionView::Base.full_sanitizer.sanitize (project.description) %></span>
<span id="p_link"><%= link_to project_path(project) %></span>
</div>
<% end %>
Create a single modal, not one for each project. Use javascript to open the modal on each link (instead of data-toggle="modal") and before you do, set the project's title, subtitle, description and link using Javascript.

Resources