Rails Kaminari example infinite scroll not working - javascript

I am trying to implement kaminari rails infinite scroll using this example.
It is working fine in my other apps but not working in this app.
Kaminari example
My company controller
def index
#companies = Company.all.page(params[:page]).per(4)
end
My index.html.erb
<div class="posts">
<div class="page">
<%= render #companies %>
</div>
</div>
<%= paginate #companies %>
My _company.html.erb
<div class="post">
<% company_decorator = CompanyDecorator.new(company)%>
<h4><%= company.name %> ||
No. of operations: <%= company_decorator.number_of_operations %> ||
Average Amount : <%= company_decorator.average_of_amount %> ||
Highest of Month: <%= company_decorator.highest_of_month%> ||
Accepted Operations: <%= company_decorator.accepted_operations%>
</h4>
<ul>
<% company.operations.each do |operation| %>
<li><%= operation.id%></li>
<%end%>
</ul>
</div>
My assets/javascripts/companies.js.coffee
$(document).ready ->
$(".posts .page").infinitescroll
navSelector: "nav.pagination"
nextSelector: "nav.pagination a[rel=next]"
itemSelector: ".posts .post"
My index.js.erb
$(".posts").append("<div class='page'><%= escape_javascript(render(#companies)) %></div>");
I am unable to find problem please help me. This same code is working in my other app.

Try
def index
#companies = Company.all.page(params[:page]).per(25)
end
playing with the pagination length.. I've heard that sometimes works

Related

How to check policies for objects created through AJAX

In my program one Board can have many Sections. On Boards#show I list all Sections for this Board. A user can create, edit and delete Sections for Boards this user has created.
I use Pundit for my authorizations.
My problem is that after having added AJAX to the create Section action, my policy checks don't work anymore. The AJAX call is working fine in that Sections are added but the "Edit" and "Delete" links are only displayed after I reload the page.
Boards#show
<% if policy(#board).edit? %>
<p><strong>Create a new Section</strong></p>
<%= render 'sections/shared/form', board: #board, section: #section %>
<% end %>
<br>
<p><strong>Sections</strong></p>
<div id="sections">
<% #board.sections.order(id: :asc).each_with_index do |section, index| %>
<span><%= "#{index + 1}. #{section.title}" %></span>
<% if policy(section).edit? %>
<%= link_to "Edit", edit_board_section_path(#board, #board.sections[index]) %>
<% end %>
<% if policy(section).destroy? %>
<%= link_to("Delete", board_section_path(#board, #board.sections[index]), method: :delete) %>
<% end %>
<br>
<% end %>
</div>
Form partial
<%= simple_form_for([#board, #section], remote: true, authenticity_token: true) do |f| %>
<%= f.input :title, id: "section_title" %>
<%= f.submit "Save" %>
<% end %>
AJAX call
var newSection = "<span><%= "#{#board.sections.length}. #{#section.title}" %></span><br>";
var sections = document.getElementById('sections');
sections.insertAdjacentHTML('beforeend', newSection);
var sectionTitle = document.getElementById('section_title');
sectionTitle.value = '';
I think the problem is that the newly created Section isn't inserted into the loop and thus the policy cannot be checked. How could I refactor my code to solve this?
You should be able to render you HTML templates into your js.erb file. See the post from the DHH https://signalvnoise.com/posts/3697-server-generated-javascript-responses how to use this properly. It is an older post so maybe some things changed but you should know what to search for. But if it still works this way, you should be able to do something like this:
Extract section to a partial _section.html.erb
<span><%= "#{index + 1}. #{section.title}" %></span>
<% if policy(section).edit? %>
<%= link_to "Edit", edit_board_section_path(#board, #board.sections[index]) %>
<% end %>
<% if policy(section).destroy? %>
<%= link_to("Delete", board_section_path(#board, #board.sections[index]), method: :delete) %>
<% end %>
<br>
Use this partial also in your Boards#show file.
Render your partial in the js.erb file
var newSection = "<span><%=j render #section %></span><br>";
Something like this should work, but I don't use server generated javascripts so they could have changed some things. But hopefully it will help you at least with the direction.

Dynamically generate copies partial form based on user selection in a nested form

I'm trying to create a form that will generate copies of a nested form depending on a user's selection. I have 3 models: Visualizations, which has_many Rows, which has_many Panes.
I want to be able to allow the user to click a small dropdown menu that will generate a row and then select 1, 2, or 3 panes. Depending on their selection, this will generate the form of their choice from a render.
here is an example where a user chose 3 panes (3 upload boxes for images) with just styled divs in place of the form
For starters. I know I would need to change up my controller a bit, but I'm not sure how to do that with a nested form since in every example I've seen so far, you need to predetermine how many times you would "build" a nested model form (not sure if that is the correct terminology). I'm not sure how to make that part dynamic.
Here is what I mean:
//visualization_controller.rb
def new
#visualization = Visualization.new
rows = #visualization.rows.build
panes = rows.panes.build
end
here is an example of the render that would be called if the usr wanted to generate a row with just 1 Pane:
<div class="medium-12 columns one_box_wrapper first" style="display:none">
<%= f.fields_for :rows, Row.new do |r| %>
<%= r.label :rowtitle %>
<%= r.text_field :rowtitle %>
<div class="nested" style="display:inline-block">
<%= r.fields_for :panes, Pane.new do |p| %>
<%= p.label :text %>
<%= p.text_field :text %>
<div class="mehv">
<img id="img_prev" width=300 height=300 src="#" alt="your image" class="img-thumbnail hidden"/> <br/>
<span class="meh">
Upload Pane Image<%= p.file_field :pane_photo, id: "pane_photo" %>
</span>
<%= p.hidden_field :pane_photo_cache %>
</div>
<% end %>
</ul>
</div>
<% end %>
</div>
Is this possible in rails? I feel like javascript would come into play but I don't think you are allowed to render server-side code through JS.
I feel a bit in over my head with this and any help would be greatly appreciated!
EDIT
I ended up using cocoon gem as it seems to have made my life a lot easier however.. I can't get the visualizations to all display on the index page! I'm not sure what the issue is.. The cover Title and Image show up but nothing else does!
//schema.rb
create_table "panes", force: :cascade do |t|
t.integer "row_id", null: false
t.text "text"
t.string "pane_photo"
end
create_table "rows", force: :cascade do |t|
t.integer "visualization_id", null: false
t.string "rowtitle"
end
create_table "visualizations", force: :cascade do |t|
t.string "title", null: false
t.string "cover_image"
end
//controller.rb
class VisualizationsController < ApplicationController
before_action :authenticate_user!, except: [:index, :show]
before_action :authorize_user, except: [:index, :show]
helper_method :resource
def index
#visualizations = Visualization.all
#visualization = Visualization.new
end
def new
#visualization = Visualization.new
rows = #visualization.rows.build
panes = rows.panes.build
end
def create
#visualization = Visualization.new(visualization_params)
if #visualization.save
redirect_to edit_visualization_path(#visualization)
else
render :new
end
end
def edit
#visualizations = Visualization.all
#visualization = Visualization.find(params[:id])
end
protected
def visualization_params
params.require(:visualization).permit(:title, :cover_image, rows_attributes: [:visualization_id, :rowtitle, panes_attributes:[:text, :pane_photo]])
end
//index.html
<div class="visual_wrap text-center">
<ul class="no-bullet text-center">
<% #visualizations.each do |visualization| %>
<li class="text-center">
<div class="row visualization text-center">
<%= image_tag visualization.cover_image.to_s, id: "visualization_image", class: "output_image" %>
<p class="visualization_title"><%= visualization.title %></p>
<p>+</p>
</div>
<div class="placeholder">
<% visualization.rows.each do |row| %>
<%= row.rowtitle %>
<% row.panes.each do |p| %>
<%= p.text %>
<%= image_tag p.pane_photo.to_s, id: "pane_image", class: "output_image" %>
<% end %>
<% end %>
</div>
</li>
<% end %>
</ul>
</div>
//new.html.erb
<% if user_signed_in? %>
<% if current_user.admin? %>
<div class="try">
<div class="breadcrumb-wrapper">
<ul class="breadcrumbs">
<%= form_for #visualization, :html => {:multipart => true} do |f| %>
<li>Preview</li>
<li><div class="separating-bar">|</div>
<li><input type="submit" name="commit" value="Save" class="save button secondary"></li>
</ul>
</div>
<div class="cover_image text-center">
<div class="row pre_img_prev">
<div class="gray_bar"></div>
<div class="img_prev">
<img id="img_preview" src="#" alt="your image" class="img-thumbnail hidden text-center"/>
<input type="text" name="visualization[title]" id="visualization[title]" class="inputtext" />
<label for="visualization[title]" id="text_preview">+ Add Title</label>
<div class="trash-can_title">
<i class="fa fa-trash fa-3x" aria-hidden="true"></i>
</div>
</div>
<input type="file" name="visualization[cover_image]" id="visualization_cover_image" class="inputfile" />
<label for="visualization_cover_image">+ Add Cover Image</label>
<%= f.hidden_field :cover_image_cache %>
<div class="trash-can_cover">
<i class="fa fa-trash fa-3x" aria-hidden="true"></i>
</div>
</div>
</div>
<div class="row linkstest">
<div class="rows">
<%= f.fields_for :rows, Row.new do |task| %>
<%= render 'row_fields', f: task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add Row", f, :rows %>
</div>
</div>
<% end %>
<% end %>
<% end %>
</div>
</div>
You don't need really need JS except to make it more "snappy". I think what you are looking for are Nested Forms.
Take a look at RaisCast it's a bit outdated but it's a good foundation.
You might want to look into Cocoon gem to help you create the new fields dynamically.
Rails nested_form inside nested_form
Update
If you don't want to use Javascript at all, you need to make an extra request to the controller to tell it to initialize (build) the rows and panes for you so that it renders the empty fields in the view.
For example:
def new
#visualization = Visualization.new
num_rows = params[:num_rows]
num_rows.each { #visualization.rows.build }
end
You would also need to have the number of panes in each row, so the parameter would have to be inside the row attributes, e.g. params[:visualization][:rows][0][:num_panes], and using that parameter you initialize the panes in the row. It's probably best to put that logic in a Factory service.
However if you create the empty fields using JS you can save yourself from making that extra request and all that logic. This is because Rails will automatically initialize (build) the rows and panes if you give it the right attributes, such as:
{
visualization: {
rows_attributes: {
# These are the attributes from an existing record
0: {
id: 39,
panes_attributes: {
0: {
id: 992
}
}
},
# This is a new set of attributes for a new record
# passed by the fields generated by cocoon where xxx
# and yyy are random numbers
xxxx: {
panes_attributes: {
yyyy: {
}
}
}
}
}
}
Then all you need to do in your controller is:
def new
# visualization_params are the permitted attributes
#visualization = Visualization.new(visualization_params)
end

Rails: Checkbox to change the value of a variable on click

I have a basic to do type app and I am trying to change the variable completed for an item to the current date/time when I click a checkbox. I found this post, which has led me to the following code structure:
My lists#show, on which items are created, checked off (updated), edited, and deleted:
<div class="container">
<div class="row" style="height: 70px"></div>
</div>
<div class="col-xs-10 col-xs-push-1 container">
<div class="md-well">
<h1 class="text-center"><%= #list.name %></h1>
<% if #items.count == 0 %>
<h4 class="text-center">You don't have any items on this list yet! Want to add some?<h4>
<% elsif #items.count == 1 %>
<h4 class="text-center">Only <%= #items.count %> Item To Go!</h4>
<% else %>
<h4 class="text-center">You Have <%= #items.count %> Items To Go!</h4>
<% end %>
<%= render 'items/form' %>
<% #items.each do |item|%>
<p>
<%= form_for [#list, item], class: "inline-block", id: 'item<%= item.id %>' do |f| %>
<%= f.check_box :completed, :onclick => "$this.parent.submit()" %>
<% end %>
<%= item.name %>
( <%= link_to "Delete", list_item_path(#list, item), method: :delete %> )
</p>
<% end %>
<div class="text-center">
<%= link_to "Back to My Lists", lists_path %>
</div> <!-- text-center -->
</div> <!-- well -->
</div> <!-- container -->
Here is my update method in my items_controller (which I believe has jurisdiction instead of the lists_controller even though it is the lists#show page because it is an item being updated:
def update
#list = List.friendly.find(params[:list_id])
#item = #list.items.find(params[:id])
#item.name = params[:item][:name]
#item.delegated_to = params[:item][:delegated_to]
#item.days_til_expire = params[:item][:days_til_expire]
#item.completed = params[:item][:completed]
#item.user = current_user
if #item.update_attributes(params[:item])
#item.completed = Time.now
end
if #item.save
flash[:notice] = "List was updated successfully."
redirect_to #list
else
flash.now[:alert] = "Error saving list. Please try again."
render :edit
end
end
Here is what is currently appearing:
And here are the two problems I'm having:
LESS IMPORTANT PROBLEM: The checkboxes should be displayed inline with the list items but aren't. My class inline-block simply makes links to this in the application.scss file:
.inline-block {
display: inline-block !important;
}
MORE IMPORTANT PROBLEM: Even after the checkbox is clicked, the value for completed remains nil as per my console:
[6] pry(main)> Item.where(name: "Feed Dexter")
Item Load (0.1ms) SELECT "items".* FROM "items" WHERE "items"."name" = ? [["name", "Feed Dexter"]]
=> [#]
Any ideas how to make this functional?

Braintree Drop-In UI requires reload to work properly

I'm just getting started with the Braintree drop-in UI. Client side is javascript, server side is ruby on rails.
My system is very simple right now. The user is given a list of invoices that pertain to them. When the invoices have not yet been paid, they can click 'pay' and be taken to a new page that includes the Braintree Drop-In UI. My issue is this: When the user is taken to the 'pay' page, the drop-in UI does not appear. If the user reloads the page, the drop-in UI appears.
Why?
Here's some relevant code. It's pretty vanilla and not done yet - just roughed in.
From invoices/index.html.erb
<td>
<% if invoice.paid %>
<%= 'Paid' %>
<% else %>
<%= link_to 'Pay', payment_path(invoice.id) %>
<% end %>
</td>
From payments_controller:
class PaymentsController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :set_invoice, only: [:pay, :checkout]
def pay
Braintree::Configuration.environment = :sandbox
Braintree::Configuration.merchant_id = 'merchant id'
Braintree::Configuration.public_key = 'public key'
Braintree::Configuration.private_key = 'private key'
gon.client_token = Braintree::ClientToken.generate()
end
def checkout
nonce = params[:payment_method_nonce]
result = Braintree::Transaction.sale :amount => #invoice.amount, :payment_method_nonce => "nonce-from-the-client"
if result.success?
message='Payment processed successfully. Thank you!'
#invoice.paid=true
#invoice.save
else
message='Unable to process payment. Reason = ' + result.message
end
redirect_to invoices_path, notice: message
end
private
def set_invoice
#invoice = Invoice.find(params[:id])
end
end
pay.html.erb:
<h1>Payments</h1>
<div>
<p>Invoice #: <%= #invoice.id %></p>
<p>Date: <%= #invoice.date %> </p>
<p>Description: <%= #invoice.description %> </p>
<p>Amount: <%= #invoice.amount %> </p>
</div>
<div class="form-container radius-box glassy-bg small-10 small-centered medium-8 large-6 columns">
<h2 class="mbs">New Transaction</h2>
<%= form_tag payments_checkout_path do%>
<%= hidden_field_tag 'id', #invoice.id %>
<p>Please enter your payment details:</p>
<div id="dropin"></div>
<%=submit_tag "Pay #{#invoice.amount}$", class: "button mt1" %>
<%end%>
</div>
and layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Actionable Software</title>
<%= include_gon %>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
<script src="https://js.braintreegateway.com/v2/braintree.js"></script>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
</head>
<body>
<%= render 'layouts/header' %>
<div class='container'>
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, class: "alert alert-info") %>
<% end %>
<%= yield %>
</div>
</body>
</html>
I'm going to guess the script that populates that element isn't written in a way that works with Turbolinks.
Try opting that page or section out of turbolinks. Or just disable it completely and see if it fixes it.
I ran into the same issue in my app.. change on your index page
<%= link_to 'Pay', payment_path(invoice.id) %>
to
<%= link_to 'Pay', payment_path(invoice.id), data: { no_turbolink: true } %>
This should force the pay page to load completeley when you click through.

jQuery - Can't get blind effect in a Rails form

I am working on a Ruby on Rails 4 project, i'm trying to use jQueryUI method show with blind effect in a form_for. The problem here is that my form will appear as expected, but the effect will not work properly. When ever I check the checkbox, the targeted div will eventually appear, but in a weird way: at first some empty space will pop-up in its place, and after 1 sec the whole div with its' content will appear.
Here is my html.erb
<%= form_for(#reserva) do |f| %>
<% if #reserva.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#reserva.errors.count, "error") %> prohibited this reserva from being saved:</h2>
<ul>
<% #reserva.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="span12 field-box">
<%= f.label :cliente_id %>
<% clientes_array = Cliente.all.map { |cliente| ["#{cliente.nombre} #{cliente.apellido}", cliente.id] } %>
<%= f.select(:cliente_id, options_for_select(clientes_array)) %>
</div>
<div class="span12 field-box">
<label >Cliente Nuevo?</label>
<%= check_box_tag 'con_cliente', 'ClienteNuevo', false %>
</div>
<div id="cliente_form">
<%= f.fields_for :cliente, #cliente do |cliente_builder| %>
<div class="span12 field-box">
<label>Nombre:</label>
<%= cliente_builder.text_field(:nombre, class: "span9") %><br />
</div>
The javascript here:
<script type="text/javascript">
$(document).ready(function(){
$("#cliente_form").hide();
$("#con_cliente").bind('change', function(){
if($(this).is(':checked')){
$("#cliente_form").show("blind");
}
else{
$("#cliente_form").hide("blind");
}
});
});
</script>
Any ideas?
Finally i solved the issue, the problem was that bootstrap and the jquery-ui have conflicts between them, and the effect can't appear as expected.

Categories

Resources