Rails 5 - show block on check box - ruby-on-rails

In my rails view (am new to rails), I want to show a div when a check box is set to true.
How should I do that?
I thought of using
<%= check_box_tag 'advancedtagging', false %> Tag details
combined with:
<% if advancedtagging = '1' %>
<div class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
<% end -%>
This is my view:
<div class="row">
<div class="col-md-4">
<div data-spy="affix">
<%= link_to 'Close', annotation_path(#annotation), :class => "btn btn-link" %>
<%= link_to 'List' , annotations_path, :class => "btn btn-link" %>
<%= check_box_tag 'advancedtagging', false %> Tag details
<%= render 'tags/form', :object => #annotation %>
<br>
<div class="panel panel-default" id="annotationResults">
<%= render 'tags/tag_list', :object => #annotation %>
</div>
</div>
</div>
<div class="col-md-8" id="file">
<%= content_tag :iframe, nil, src: pdf_annotation_path(#annotation), width: "100%", height: "875px", frameBorder: "0" %>
</div>
</div>
<% if advancedtagging = '1' %>
<div class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
<% end -%>

Put an id to your div and your checkbox
<div id="mydiv" class="row">
<%= render 'tags/advanced', :object => #annotation %>
</div>
Using Jquery
$(function() {
$('#mycheckbox').click(function(event){
event.preventDefault();
$('div#mydiv').toggle();
});
});
Add your CSS file div.hidden { display: none; }
Using pure js
Add in some js file for example application.js or other you want
$(function() {
var mycheckbox = document.getElementById('mycheckbox');
var mydiv = document.getElementById('mydiv');
var toggleDiv = function(){
if(mycheckbox.checked) {
mydiv.style['display'] = 'block';
} else {
mydiv.style['display'] = 'none';
}
}
mycheckbox.onclick = toggleDiv;
toggleDiv();
});

Related

Deep rails nested attributes on the fly

I have a form, the form has 'fields_for :addresses' and renders partial 'address_fields' in that 'fields_for :addresses', in that partial 'address_fields' there is 'fields_for :sub_address', when the browser is first loaded, the 'fields_for :sub_address' in the partial 'address_fields' appears, but when the 'Add Addresses' button is pressed the "fields_for :sub_address" element does not appear. So basically I have a nested form inside the nested form 'addresses', but it doesn't render when I click on 'Add Address'.
This is my 'Add Address' javascript code:
class AddFields {
constructor() {
this.links = document.querySelectorAll('.add_fields');
this.iterateLinks();
}
iterateLinks() {
if (this.links.length === 0) return
this.links.forEach(link => {
link.addEventListener('click', e => {
this.handleClick(link, e)
});
});
}
handleClick(link, e) {
if (!link || !e) return;
e.preventDefault();
let time = new Date().getTime();
let linkId = link.dataset.id;
let regexp = linkId ? new RegExp(linkId, 'g') : null
let newFields = regexp ? link.dataset.fields.replace(regexp, time) : null
newFields ? link.insertAdjacentHTML('beforebegin', newFields) : null
}
}
window.addEventListener('turbolinks:load', () => new AddFields());
here is my views:
new.html.erb
<%= form_with model: #data, url: address_path(token: params[:token]) do |form| %>
<div class="row">
<div class="col">
//another html here
</div>
</div>
<fieldset>
<div class="card mt-2">
<div class="card-body">
<%= form.fields_for :address do |addr| %>
<%= render 'sub_address_fields', form: addr %>
<% end %>
<%= link_to_add_fields 'Add Address', form, :addr %>
</div>
</div>
</fieldset>
<div class="form-group">
<%= form.submit :'Submit', name: 'submit', class: 'btn btn-primary mt-2' %>
</div>
<% end %>
```
partial view:
<div class="nested-fields">
<%= form.hidden_field :_destroy %>
<div class="row">
<div class="col">
//another html here
</div>
<%= form.fields_for :sub_address do |sub_addr| %>
<div class="row">
<div class="col">
<div class="form-group mt-2">
<div class="custom-file form-control">
<%= sub_addr.label :id_card, class: 'id-card-label', for: 'id-card-file' %>
<%= sub_addr.file_field :attachment_id_card, id: 'id-card-file' %>
</div>
</div>
</div>
<div class="col">
<div class="form-group mt-2">
<div class="custom-file form-control">
<%= sub_addr.label :self_assessment, class: 'self-assessment-label', for: 'self-assessment-file' %>
<%= sub_addr.file_field :attachment_self_assess, id: 'self-assess-file' %>
</div>
</div>
</div>
<div class="col">
<div class="form-group mt-2">
<div class="custom-file form-control">
<%= sub_addr.label 'SWAB', class: 'swab-label', for: 'swab-file' %>
<%= sub_addr.file_field :attachment_swab, id: 'swab-file' %>
</div>
</div>
</div>
</div>
<% end %>
<div class="form-group">
<%= link_to "Remove", '#', class: "remove_fields"%>
</div>
</div>
and this is the helper:
module Frontend::Data::DataHelper
def link_to_add_fields(name, form, association)
new_object = form.object.send(association).klass.new
id = new_object.object_id
fields = form.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + '_fields', form: builder)
end
link_to(name, '#', class: 'add_fields', data: {id: id, fields: fields.gsub('\n', '')})
end
end
Is javascript not able to display the form generated from the 'render' function on rails?

Rails Submit button not submitting

I've moved from BS3 to Materialize so I am going through and changing my forms - I have 4 forms that are extremely similar, but as I switched the first one over it's no longer submitting. The button doesn't even seem like it's getting clicked, but I tied a generic 'logMe' function to it and sure enough it is.
My routes are the exact same for both, the new form is
<div class="row">
<%= form_with(model: #statement, local: true) do |form| %>
<% if #statement.errors.any? %>
<% #statement.errors.full_messages.each do |message| %>
<script>
$(function() {
Materialize.toast("<%= message %>", 3000);
});
</script>
<% end %>
<% end %>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">account_circle</i>
<!--<label for="icon_prefix">SoW Type:</label>-->
<%= form.label :statement_type, 'Type:' %>
<%= form.text_field :statement_type, :id => "disabled", :value => (params[:statement_type]), readonly: true, :disabled => true %>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix">contacts</i>
<%= form.label :name, "Name:" %>
<%= form.text_field :name, :id => 'required_field1' %>
</div>
<div class="input-field col s6">
<i class="material-icons prefix">contacts</i>
<%= form.label :cost, "Cost:" %>
<%= form.text_field :cost, :id => 'required_field2' %>
</div>
</div>
<div class="row">
<div class="input-field col s6">
<i class="material-icons prefix">date_range</i>
<%= form.label :start_date, "Start Date" %>
<%= form.text_field :start_date, :class => 'datepicker', "data-provide" => 'datepicker', :id => 'required_field4', :placeholder => "YYYY-MM-DD" %>
</div>
<div class="input-field col s6">
<i class="material-icons prefix">date_range</i>
<%= form.label :end_date, "End Date" %>
<%= form.text_field :end_date, :class => 'datepicker', "data-provide" => 'datepicker', :id => 'required_field5', :placeholder => "YYYY-MM-DD" %>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">perm_contact_calendar</i>
<%= form.collection_select(:client_id, current_user.clients.order(:name),:id,:name, :class => "browser-default", :prompt => "Choose a client" ) %>
</div>
</div>
<div class="row">
<div class="col s12">
<%= form.submit 'Submit', :class =>'btn btn-default', :id => 'register', :onclick => "testMe()"%>
</div>
</div>
<% end %>
</div>
<script type="text/javascript">
$(document).ready(function (){
$('select').material_select();
validate();
$('#required_field1, #required_field2').change(validate);
});
function testMe(){
console.log('hi')
}
function validate(){
if ($('#required_field1').val().length > 0 &&
$('#required_field2').val().length > 0
){
$("input[type=submit]").prop("disabled", false);
}
else {
$("input[type=submit]").prop("disabled", true);
}
}
var from_$input = $('#required_field4').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15, // Creates a dropdown of 15 years to control year,
today: 'Today',
clear: 'Clear',
close: 'Ok',
closeOnSelect: true,
format: 'yyyy-mm-dd'
}),
from_picker = from_$input.pickadate('picker')
var to_$input = $('#required_field5').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15, // Creates a dropdown of 15 years to control year,
clear: 'Clear',
close: 'Ok',
closeOnSelect: true,
format: 'yyyy-mm-dd'
}),
to_picker = to_$input.pickadate('picker')
// Check if there’s a “from” or “to” date to start with.
if ( from_picker.get('value') ) {
to_picker.set('min', from_picker.get('select'))
}
if ( to_picker.get('value') ) {
from_picker.set('max', to_picker.get('select'))
}
// When something is selected, update the “from” and “to” limits.
from_picker.on('set', function(event) {
if ( event.select ) {
to_picker.set('min', from_picker.get('select'))
}
else if ( 'clear' in event ) {
to_picker.set('min', false)
}
})
to_picker.on('set', function(event) {
if ( event.select ) {
from_picker.set('max', to_picker.get('select'))
}
else if ( 'clear' in event ) {
from_picker.set('max', false)
}
})
</script>
I've tried commenting out all JS, switching it to a regular button, linting it and using Rubocop but I don't see anything off. I went through the HTML to make sure the button was inside the form, and it is.
This isn't the first form I've transitioned, but the first I'm having issues with.
(I assume only the view is relevant since it isn't getting to the controller at this point.)
Just to be safe - The view rendering the form is
<div class="row">
<div class="col s12"><span class="flow-text" style="text-align: center;"><h1>New <%= params[:statement_type] %></h1></span></div>
</div>
<% if params[:statement_type] == 'Proposal' %>
<%= render 'proposal_form' %>
<% elsif params[:statement_type] == 'Concept' %>
<%= render 'concept_form' %>
<% elsif params[:statement_type] == 'SoW' %>
<%= render 'sow_form' %>
<% elsif params[:statement_type] == 'Misc' %>
<%= render 'misc_form' %>
<% end %>
<%= link_to 'Back', statements_path %>
SoW + Proposal work. SoW doesn't.
My issue ended up not being HTML based, but Rails based in the end.
My static element that is populated by a param was causing the issue.
<%= f.text_field :statement_type, :id => "disabled", :value => (params[:statement_type]), readonly: true %>
By removing the id: disabled it resolved the inability for the Submit button to submit. Unfortunately, it also makes MaterializeCSS back to highlighting the field when I select it, but my issue was the Submit button not working.

How to perform POST operation in Rails using AJAX

Scenario
I have created a simple application for learning Rails and Bootstrap. What this application does is it allows users to give nicknames to celebrities and like the nicknames as well. You can check it at http://celebnicknames.herokuapp.com
I have got a link_to button for posting likes for a celebrity in my home/index.html.erb as:
<%= link_to home_updatelike_path(id: nickname.id, search: #search ), method: :post, remote: true, class: "update_like btn btn-xs btn3d pull-right" do %>
<i class="glyphicon glyphicon-thumbs-up"></i>
<% end %>
The corresponding code in my home_controller.rb for the post method is:
def updatelike
#like = Like.new(:nickname_id => params[:id], :ip_address => request.remote_ip)
#like.save
respond_to do |format|
format.html { redirect_to root_path("utf8"=>"✓", "search"=>params[:search], "commit"=>"Search") }
format.json { head :no_content }
format.js { render :layout => false }
end
end
The code in my updatelike.js.erb is as:
$('.update_like').bind('ajax:success', function() {
});
Now, what I want to achieve is to submit a like without performing a page reload.
Problem:
Whenever I press the button, the database operation is done, but the change is not reflected in the page unless I reload it. Please guide me through this noob question and also provide links to resources which explain using AJAX with Rails.
Edit
Here is the entire home/index.html.erb
<div class="jumbotron col-md-6 col-md-offset-3">
<h1 class='text-center'>Nicknamer</h1>
</div>
<div class="container">
<div class="row">
<div class="col-sm-8 col-sm-offset-2 bottom50">
<%= form_tag(root_path, :method => "get", id: "search-form", type: "search") do %>
<div class = "form-group" >
<div class = "col-sm-9 " >
<%= text_field_tag :search, params[:search], placeholder: "Name", class: "form-control" %>
</div>
<div class = "col-sm-3" >
<%= submit_tag "Search", class: "btn btn-default btn-block btn-success"%>
</div>
</div>
<% end %>
</div>
</div>
<% #names.each do |name| %>
<div class="col-md-6 col-xs-8 col-md-offset-3 col-xs-offset-2 bottom50">
<!-- ===== vCard Navigation ===== -->
<div class="row w">
<div class="col-md-4">
<% if name.sex == true %>
<%= image_tag("mal.jpg", :alt => "", class: "img-responsive") %>
<% else %>
<%= image_tag("fem.jpg", :alt => "", class: "img-responsive") %>
<% end %>
</div><!-- col-md-4 -->
<!-- ===== vCard Content ===== -->
<div class="col-md-8">
<div class="row w1">
<div class="col-xs-10 col-xs-offset-1">
<h3><%= "#{name.name}" %></h3>
<hr>
<h5>Also known as</h5>
<% name.nicknames.each do |nickname| %>
<div class = "row w2 bottom10">
<% if nickname.name_id == name.id %>
<div class="col-xs-7">
<%= nickname.nickname %>
</div>
<div class="col-xs-3 text-right">
<%= pluralize(nickname.likes.count, 'like') %>
</div>
<div class="col-xs-1">
<%= link_to home_updatelike_path(id: nickname.id, search: #search ), method: :post, remote: true, class: "update_like btn btn-xs btn3d pull-right" do %>
<i class="glyphicon glyphicon-thumbs-up"></i>
<% end %>
</div>
<% end %><!-- if -->
</div><!-- row w2 -->
<% end %><!-- do -->
<div class = "row w3 bottom30">
<%= form_for #addnickname, as: :addnickname, url: {action: "addnickname"} do |f| %>
<div class = "form-group" >
<%= f.hidden_field :name_id, :value => name.id %>
<%= f.hidden_field :search, :value => #search %>
<div class = "col-xs-9">
<%= f.text_field :nickname , :required => true, class: "form-control" %>
</div>
<div class = "col-xs-3">
<%= f.submit "Add", class: "btn btn-default btn-info"%>
</div>
</div>
<% end %>
</div>
</div><!-- col-xs-10 -->
</div><!-- row w1 -->
</div><!-- col-md-8 -->
</div><!-- row w -->
</div><!-- col-lg-6 -->
<% end %>
</div><!-- /.container -->
and this is the entire home_controller.rb
class HomeController < ApplicationController
def index
#addnickname = Nickname.new
if params[:search]
#search = params[:search]
#names = Name.search(params[:search])
else
#names = Name.all
end
end
def addnickname
#addnickname = Nickname.new(:nickname => params[:addnickname][:nickname], :name_id => params[:addnickname][:name_id])
if #addnickname.save
redirect_to root_path("utf8"=>"✓", "search"=>params[:addnickname][:search], "commit"=>"Search")
else
render :new
end
end
def updatelike
#like = Like.new(:nickname_id => params[:id], :ip_address => request.remote_ip)
#like.save
respond_to do |format|
format.html { redirect_to root_path("utf8"=>"✓", "search"=>params[:search], "commit"=>"Search") }
format.json { head :no_content }
format.js { render :layout => false }
end
end
private
def addnickname_params
params.require(:addnickname).permit(:name_id, :nickname, :search)
end
end
Ok, so you need a way to identify the div with the number that needs to change:
<div class="col-xs-3 text-right">
<%= pluralize(nickname.likes.count, 'like') %>
</div>
The easiest way to do this would be to have an id attribute on the div that corresponds to the (unique) database id of the nickname. Rails has a helper method for this called div_for. So you could change the above code to this:
<%= div_for(nickname, class: "col-xs-3 text-right") do %>
<%= pluralize(nickname.likes.count, 'like') %>
<% end %>
That will generate a div with an id like nickname_1 (if this id of the nickname is 1).
Now in your javascript template you can easily target the div that needs to be updated:
$("nickname_#{#like.nickname.id}").html(#like.nickname.likes.count);
The ajax:success binding is unnecessary here since you are rendering a javascript template. In the template you can access instance variables set in the controller - just like you can from an HTML template. The above code is meant to replace the content of the div that contains the likes count with the new count.

how to implement pagination with multistep?? OR is their any way to hold the previous page radio button value when using pagination

I am creating a rails quiz .. i have done everything the problem is that i want to implement pagination and when the user goes to next page the previous page values are lost. i am new to rails.
view page -- that show question paper
<div class="navbar navbar-fixed-top">
<h3><% if #paper.timing!=0 %><div id="time" class="bg"></div><%end%></h3>
</div>
<br>
<%= form_for Result.new do |f| %>
<div id="content">
<div class="inputs">
<div>
<div>
<div>
<div>
<% #questions.each_with_index do |question , i | %>
<%= f.hidden_field :userchoice_id, :value => session[:id] %>
<%= f.hidden_field :exam_id, :value => session[:exam_id] %><br>
<h3> <%= i + 1 %>.<%= question.content %></h3><br>
<%count = 0%>
<% a=question.answers %>
<%#raise a.inspect%>
<% a.each do |sushil| %>
<%#raise sushil.inspect%>
<% if sushil.correct_answer?%>
<%count = count+1 %>
<%else %>
<%count = count+0 %>
<%end%>
<%end%>
<%#raise count.inspect%>
<%if count == 1 %>
<% for answer in question.answers %>
<%= radio_button_tag("result[question_id][#{question.id}]", answer.id ) %>
<%= answer.content %><br>
<%end%>
<%elsif count >= 2 %>
<% for answer in question.answers %>
<%= check_box_tag("result[question_ids][][#{question.id}]", answer.id ) %>
<%#= check_box_tag ("result[question_id][#{question.id}]", answer.id ) %>
<%= answer.content %><br>
<% params[:answer_id] = answer.id %>
<%end%>
<% end %>
<%# raise params[:answer_id].inspect%>
<% end %>
</div>
<div class="form-actions">
<center><%= f.submit "Submit", :class => 'btn btn-primary',:onclick => "if(confirm('Are you sure you want to Submit the Paper?')) return true; else return false;" %></center>
</div>
<% end %>
</div>
</div>
</div>
<div style='display:none' id="timeup"><% if #time==0 %>0<%else%>1<%end%></div>
<!-- Added javascript for back button-->
<script>
jQuery(document).ready(function($) {
if (window.history && window.history.pushState) {
window.history.pushState('forward', null, './#forward');
$(window).on('popstate', function() {
history.forward();
});
}
});
</script>
<!-- Added Timer Javascript in Test -->
<% if #paper.timing!=0 %>
<script>
$(document).ready(function(){
var now=new Date();
if($('#timeup').html()==0){
stopTest();
}
now.setMinutes(now.getMinutes()+<%=#min%>);
now.setSeconds(now.getSeconds()-<%=#sec%>);
$('#time').countdown({until:now, format: 'MS',onExpiry:stopTest});
});
function stopTest(){
$('#time').html('<center><h4>Time\'s up!</h4></center>');
$('#timeup').html('0');
// $('input.radio').attr("onclick","return false;");
$("#new_result").submit();
}
</script>
<%end%>
You should use kaminari or will_paginate gem...
Kaminari example:
Gemfile:
gem 'kaminari'
bash:
bundle
rails g kaminari:views default
products_controller.rb:
#products = Product.order("name").page(params[:page]).per(5)
config/locales/en.yml:
en:
hello: "Hello world"
views:
pagination:
previous: "< Previous"
next: "Next >"
truncate: "..."
products/index.html.erb:
<%= paginate #products %>
app/views/kaminari/_prev_span.html.erb
<span class="prev disabled"><%= raw(t 'views.pagination.previous') %></span>
Will_paginate example:
http://richonrails.com/articles/getting-started-with-will-paginate

Rendering a collection isn't rendering all items in the collection?

This seems very elementary, so I'm not sure what I'm doing wrong. I have a #videos collection (which debugging #videos.count reveals to be 4), but the line <%= render #videos %> is only rendering 2 of the 4 items. Here is the controller method (VideosController):
def index
#video = Video.new(athlete_id: current_user.id, sport_id: current_athlete_sport.id)
#videos = current_user.videos_for_sport(current_athlete_sport).order("date DESC")
debugger
respond_with #videos
end
And the _video partial that the aforementioned <%= render #videos %> line is rendering:
<%= form_for video do |f| %>
<div class="row edit-video-container <%= video == #videos.pop ? 'last' : '' %>">
<div class="span4">
<div class="row">
<div class="span4 video-thumbnail">
<%= image_tag video.thumbnail_url || asset_path("video-encoding-placeholder.png"), {alt: "", title: "#{video.name || "My video" + video.id}"} %>
<div class="video-ribbon">
<ul>
<li class="pull-left">
<%= link_to "#video-player-modal", { data: { toggle: "modal", link: video.mp4_video_url, thumbnail: video.thumbnail_url }, role: "button", class: "video-player-link" } do %>
<i class="icon video-play"></i>
<p>Play</br>Video</p>
<% end %>
</li>
<li class="pull-left">
<%= link_to rotate_video_path(video, direction: "ccw"), :data => { :method => "put", :confirm => "Are you sure?", :type => 'json' } do %>
<i class="icon video-rotate-left"></i>
<p>Rotate</br>Left</p>
<% end %>
</li>
<li class="pull-left">
<%= link_to rotate_video_path(video, direction: "cw"), :data => { :method => "put", :confirm => "Are you sure?", :type => 'json' } do %>
<i class="icon video-rotate-right"></i>
<p>Rotate</br>Right</p>
<% end %>
</li>
<li class="pull-left">
<%= link_to video_path(video), :data => { :method => "delete", :confirm => "Are you sure?", :type => 'json' } do %>
<i class="icon video-delete"></i>
<p>Delete</br>Video</p>
<% end %>
</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="span4">
<%= f.check_box :featured, { checked: video.featured?, class: "autosave checkbox-right", data: { event: 'change' } } %>
<%= label_tag "video-checkbox-featured-#{video.id}", "Use as featured video?", { class: "checkbox-right-label" } %>
</div>
</div>
</div>
<div class="span4">
<div class="row">
<div class="span4">
<%= label :video, :name, "Video Name" %>
<%= f.text_field :name, { class: "span4 autosave"} %>
</div>
</div>
<div class="row">
<div class="span4">
<%= label :video, :video_type_id, "Video Type" %>
<%= f.select:video_type_id, VideoType.all.collect { |vid| [vid.name, vid.id] }, { include_blank: "Choose One", selected: video.video_type_id }, { class: "chosen-select autosave", id: "", data: { event: 'change' } } %>
</div>
</div>
<div class="row">
<div class="span4">
<%= label :video, :sport_id, "Video Sport" %>
<%= f.select :sport_id, current_user.sports.collect { |sp| [sp.name, sp.id] }, { include_blank: "Choose one", selected: video.sport_id }, { class: "chosen-select autosave", id: "", data: { event: "change" } } %>
</div>
</div>
<div class="row">
<div class="span4">
<%= label :video, :date, "Date Recorded" %>
<%= f.text_field :date, {class: "autosave date datePicker span4", value: js_date(video.date) } %>
</div>
</div>
<div class="row">
<div class="span4">
<%= label :video, :uniform_number, "Uniform Number" %>
<%= f.text_field :uniform_number, { class: "autosave span4"} %>
</div>
</div>
</div>
</div>
<% end %>
Again, throwing a debugger in the controller, or a debug on the page just before the <%= render #videos %> line shows 4 videos, however only 2 are actually being rendered. At a bit of a loss here!
The problem is here:
video == #videos.pop
Pop takes out a member from your collection. You shouldn't use it here because you brake the looping.
If this is the case, I suppose you can see only the first and the last item of your collection.

Resources