Adding a dynamic field via javascript on RoR - javascript

I would like to add dynamically fields to a form in a ERB file and I'm getting an issue that I don't know how to fix.
Basically, a user clicks a btn on a form and a new input text field is added via javascript. Right now, my code looks like this:
<div class="form-group row">
<button type="button" class="btn onclick="addManualInputFieldBtnPressed()">Add a manual input field</button>
</div>
<div id="manual_input_fields">
</div>
and my javascript looks like this:
<script>
var fields_index = -1;
function addManualInputFieldBtnPressed() {
fields_index += 1;
$("#manual_input_fields").append('<div class="form-group row">\
<%= form.label :new_text, class:"col-lg-3" %>\
<div class="col-lg-9">\
<%= form.text_area :new_text, class:"form-control", size: "20x5" %>\
</div>\
</div>');
}
</script>
If I add simple text it works, but as if I have the code above, I'm getting...
undefined local variable or method `form' for #<#<Class:0x00007fbf5c719940>:0x00007fbf5cc13108>
Did you mean? for
fork
I also tried with this code on my javascript part and I get a different error (related to rendering) but it didn't work either.
$("#manual_input_fields").append('<%= escape_javascript(<div class="form-group row">\
<%= form.label :description, class:"col-lg-3 font-weight-bold text-dark col-form-label form-control-label text-2" %>\
<div class="col-lg-9">\
<%= form.text_area :description, class:"form-control", size: "20x5" %>\
</div>\
</div>).html_safe %>');
Can someone point me to the right direction? I suppose that it must be something obvious but I'm a newbie on RoR.

Related

Flatpickr Clear Button

I'm loading flatpickr using this:
<script type="text/javascript">
jQuery(document).ready(function($){
$('#Mydatetime').flatpickr({
altInput: true,
altFormat: "M j, Y # H:i",
enableTime: true,
dateFormat: 'Y-m-d\\TH:i'
});
});
<input type="text" id="Mydatetime" class="MyDate" name="my_expire_date" value="' . $variable . '"/>
The variable is just my datetime. It works, but I'd like to add a clear button similar to this. No matter what I do the button doesn't clear the date.
The example:
<a class="input-button" title="clear" data-clear>
<i class="icon-close"></i>
</a>
Seems straightforward, but I'm clearly missing something. Anyone got one of these close buttons working properly?
Use the following method:
const $flatpickr = $("#flatpickr_id").flatpickr();
$("#some_button_id").click(function() {
$flatpickr.clear();
})
$(function() {
$(".input_button").click(function() {
$('#Mydatetime')[0]._flatpickr.clear();
});
});
Just add this button to your HTML:
<button class="clear_button" title="clear" data-clear>
Clear
</button>
And add this code to the inside of "document ready" function
$(".clear_button").click(function() {
$('#Mydatetime').flatpickr().clear();
})
Here is an working example: https://codepen.io/anon/pen/pxKOGP
If not using jQuery, you can try this:
const my_fp = document.querySelector("#fp_field")._flatpickr;
my_fp.clear();
You can achieve it using CoffeeScript/JS. Unfortunately, there is no option provided by the flatpickr to clear the field after selection.
Envoirenment: Rails & coffeescript
View:
<div class="form-group flatpicker">
<%= f.label :start_time_gt_eq, 'Starting at', class: 'form-control-label font-weight-bold' %>
<div class="row d-flex justify-content-between ml-1">
<%= f.text_field :start_time_gt_eq, class: 'form-control active position-relative col-md-11' ,
data: {
behavior: 'flatpickr_time',
enable_time: true,
alt_input: true,
} %>
<button type="button" id="appointment-start-from" class="close" data-dismiss="alert">×</button>
</div>
</div>
CoffeeScript file
(->
window.Appointments or (window.Appointments = {})
Appointments.init = ->
$ ->
$('#appointment-start-from').click ->
$('#q_start_time_gt_eq').flatpickr().clear();
return
).call this
And make sure to initialize the JS in the view file
<% content_for :js_init do %>
Appointments.init();
<% end %>

Open Semantic UI Calendar within a loop

I need to open Semantic-UI-Calendar within a loop but nothing works, which it should. The logic is, when I click data-id="expensecal", it should give me the id which is expense_date2 or expense_date1 but instead it give me the id of the input:
Rails View:
#---Loop----#
<div class="required field">
<label>Claim date</label>
<div class="ui calendar" data-id="expensecal" id="expense_date<%= contract.id %>">
<div class="ui input left icon">
<i class="calendar icon"></i>
<%= f.text_field :date, id: "expense_date_input", placeholder: "Expense date" %>
</div>
</div>
</div>
JavaScript:
$( "[data-id=expensecal]" ).click(function(e) {
e.preventDefault();
let id = '#' + e.target.id;
console.log(id); // Shows the field input id. Why?
$(id).calendar({
type: 'date'
});
});
I use this method to open up a semantic modal in a loop and it works ok but not sure why not with the calendar.
Initialize all the elements at page ready using a class, remove the click event
Try using the following code:
$('.ui.calendar').calendar({
type: 'date'
});
demo:https://jsbin.com/kenaqiyuqe/1/edit?html,js,output

List.js is returning wrong results

I'm using List.js for the first time. I really liked it, and in the moment I am using it together with rails 4.2 to create a Pokémon team creator tool.
I am also using jQuery 1.11.3 as the JavaScript library for rails.
I have this right now:
It's coded like this:
<script>
var options = {
valueNames: ['name']
};
var userList = new List('pokemons', options);
</script>
<div id="pokemons">
<input class="search form-control" placeholder="Search" />
<ul class="list" style="list-style: none; padding:0; margin:0;">
<% PokemonDefault.where(forme: nil).each do |pokemon| %>
<li>
<div class="name">
<%=image_tag 'miniaturePokemon/'+pokemon.code+'.png' %>
<%=pokemon.name %>
</div>
</li>
<% end %>
</ul>
</div>
It gets all pokémon from PokemonDefaults table, and shows their image and name.
However, List.js is acting weird when I type stuff like 'baa':
As you can see, any of this pokémon has "baa" in their name.
What is happening?
I would assume that List is getting confused because you have an img tag in your div. Try rendering your html like:
<li>
<%=image_tag 'miniaturePokemon/'+pokemon.code+'.png' %>
<span class="name"><%=pokemon.name %></span>
</li>

How to implement a function like stackoverflow's `add a comment` in Rails' app?

I am trying to implement a mini SO with Rails, and find SO's add a comment under every question and answer very interesting and difficult for me:
after you click add a comment link, add a comment link will hide and a form with textarea and submit will show.
At the beginning, for a question with activity No 47, I implement this using the snippet code like this:
<div id="comments" class="comments">
<button type="button" id="comment-btn-47">add a comment</button>
<div id="new-comment-47" style="display:none">
...
</div>
</div>
and when clicking add a comment using code:
<% content_for :javascript do%>
$("#comment-btn-47").click(function(){
$("#new-comment-47").show(0, function(){
$("#comment-btn-47").hide() });
<% end %>
NOTE:here `47` is the answer activity No
after writing the content for a comment and clicking the button called submit, the last part of saving and showing the comments include the following code:
$("#new-comment-47").hide();
$("#comment-btn-47").show();
It works fine when a question does not answer, but when a question has one or more than one answers, the above resolution fails. After thinking simply about it, I find that <% content_for :javascript do %> ... <% end %> needs a more complicated resolution, for example, if there is a question with No 47 and a corresponding answer with No 74, so in <% content_for :javascript do %> ... <% end %>, I need:
<% content_for :javascript do%>
$("#comment-btn-47").click(function(){
$("#new-comment-47").show(0, function(){
$("#comment-btn-47").hide() });
$("#comment-btn-74").click(function(){
$("#new-comment-74").show(0, function(){
$("#comment-btn-74").hide() });
<% end %>
Obviously, this not a idea resolution, what should I do? what things about javascript, rails or css I missed? Thank you in advance!
Most of your difficulties are due to the fact that you are abusing element ID's. ID's are great for truly unique elements, but just usings ID's makes it extremely difficult to make good reusable code or moving your javascript out of your views where it has no place being in the first place.
$('.answer, .question').on('click', '.add-a-comment', function(){
var $button = $(this);
$button.hide(); // hide the button
// go up to the parent question
// and the look down to find form.
$button.parents('.answer, .question')
.find('.comment-form').removeClass('hidden');
});
// Silly example of adding an event handler and traversing
$('.answer, .question').on('submit', '.comment-form', function(){
var $form = $(this);
var $comments = $form.parents('.answer, .question')
.find('.comments');
$comments.append('<li>' + $form.find('textarea').val() + '</li>');
});
.hidden { display: none }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="question">
<!-- ... -->
<section class="comments-box">
<p>Blablabla...?</p>
<ul class="comments">
<li class="comment">Say what?</li>
<!-- ... -->
</ul>
<p>
<button type="button" class="add-a-comment">add a comment</button>
</p>
<form class="comment-form hidden">
<input type="hidden" name="comment[question_id]" value="3">
<textarea name="comment[body]"></textarea>
<input type="submit" value="submit comment">
</form>
</section>
</div>
<div class="answer">
<!-- ... -->
<section class="comments-box">
<p>Just add water</p>
<ul class="comments">
<li class="comment">This is silly.</li>
<!-- ... -->
</ul>
<p><button type="button" class="add-a-comment">add a comment</button></p>
<form class="comment-form hidden">
<input type="hidden" name="comment[answer_id]" value="5">
<textarea name="comment[body]"></textarea>
<input type="submit" value="submit comment">
</form>
</section>
</div>

Ruby Rails - optional form input shown conditional on checkbox

I am working on a dynamic form input display where if the users clicks something to show "advanced options" in the form, the input vectors will be displayed, but otherwise (the default) they will not be shown. I have the following pieces in my form partial:
UPDATED 1x:
<div class="form-inputs">
<%= f.input :message, label: 'Write message'%>
</div>
<div class="form-inputs">
<%= f.check_box :advanced, {}, :id => "advancedbox" %>
</div>
<div class="form-inputs" id="advancedopts" style="display:none;">
<%= f.input :startdatetime, label: 'Specify', :as => :datetime_picker %>
<%= f.input :expirationdatetime, label: 'Specify', :as => :datetime_picker %>
</div>
And the JS in the head of the form partial:
UPDATED 1x:
<head><script type="text/javascript">
var checkbox = document.getElementById('advancedbox');
checkbox.onchange = function() {
if (checkbox.checked) {
document.getElementById("advancedopts").style.display = "block;";
} else {
document.getElementById("advancedopts").style.display = "none;";
}
}
</script></head>
I took the inspiration for this from the following post: show rest of a form if a checkbox is ckecked in ruby on rails
But I cannot get it to work: the checkbox shows, but clicking it on or off does not show my advanced form inputs. Can anyone help me debug?
Thanks!!
Your problem is that there is no event being listened for. In the example you linked, checkbox.onchange is an event that triggers a function (action) that displays the div. As yours is all namespaced within a function with no event to fire it, nothing happens as it is not evaluated when the state of your checkbox changes.
So if you move the line
var checkbox = document.getElementById('advancedbox');
outside your show function and then key the onchange event to that variable as in the example you linked, it should work.
EDIT: jQuery solution...
$(document).ready(function(){
$("#advancedbox").change(function(){
if( $(this).is(':checked') ){
$('#advancedopts').show(); // you could instead animate using .fadeIn() or .slideDown() if that was preferable
} else {
$('#advancedopts').hide(); // ditto above, using .fadeOut(), .slideUp() etc.
}
});
});
Your problem is here:
<div class="form-inputs" name="advancedopts" style="display:none;">
Changing the name attribute to id should do the trick:
<div class="form-inputs" id="advancedopts" style="display:none;">
Because I do not need to save the user selection, I use the following which works well for my purposes (inspired by changing DIV visibility with JavaScript):
in form partial:
<input type="button" value="Show advanced" onClick="show()">
<div class="form-inputs" id="advancedopts">
... </div>
in application.js:
function show(){
document.getElementById("advancedopts").style.visibility= 'visible' ;
}
in scaffolds.css:
#advancedopts{
visibility:hidden;
}
And works sufficiently for me without the use of a listener. Just in case anyone has a similar simple need and starts off on a track-more-complicated-than-necessary like me.

Categories