I have a form containing some dynamically added date fields using jQuery, In order to handle their params submitted I need to count the number of those fields, then inside the controller I can make a loop based on that number:
application.js
$(function() {
var scntDiv = $('#foo');
var i = $('#foo div.bar').size();
$(document).on('click', '#addField', function() {
$('<div class="bar"><input type="text" id="start" name="start_'+ i +'"><input type="text" id="end" name="end_'+ i +'"></div>').appendTo(scntDiv);
i++;
return false;
});
Saying I added n input, then the html output will be:
<input type="text" id="start" name="start_1">
<input type="text" id="end" name="end_1">
.
.
.
<input type="text" id="start" name="start_n">
<input type="text" id="end" name="end_n">
My question is, how to access that "n" inside my controller?
I have to store all the dates range in one array then create multiple records based on each date.
Another option, close to how nested_attributes are implemented (not the most beautiful javascript you'll see out there, but you get the spirit) :
$(function() {
var $scntDiv = $('#foo');
$('#addField').click( function(){
var index = $scntDiv.find( '.bar' ).size();
$(
'<div class="bar">' +
'<input type="text" class="start" name="ranges[' + index + '][start]">' +
'<input type="text" class="end" name="ranges[' + index + '][end]">' +
'</div>'
).appendTo( $scntDiv );
return false;
});
});
This will build a hash like this :
>> params[:ranges]
=> {"0" => {"start" => "a_date_string", "end" => "another_date_string"},
"1" => {"start" => "a_date_string", "end" => "another_date_string"} }
it's then easy to process this hash, even using mass assignment :
class MyClass
def ranges= ranges
ranges.each do |*,attributes|
# whatever logic pleases you, self.ranges.build( attributes ) for instance
end
end
end
however, if you go this way, you better use directly nested_attributes, except if you have a very convoluted logic to perform. Nested attributes come with a lot of goodies like auto instantiation of child records, record deletion management, auto-rejection of some attributes if needed, they work well with the fields_for form helper, etc. It's native to rails, so why bother and reinvent the wheel ?
This will help.
$(function() {
var scntDiv = $('#foo');
$('#addField').click(function(){
$('<div class="bar"><input type="text" id="start" name="start[]"><input type="text" id="end" name="end[]"></div>').appendTo(scntDiv);
return false;
});
});
This will send the params like below. for example
"start"=>["1", "2", "3"], "end"=>["11", "22", "33"]
Related
I know this question has being done here a lot but I looked and tried a lot of answers, wasn't able to retrieve what i need.
First, I pass a value from an item using django forms through the view. In this example, the template receive the value of "900" because I use the default {{form.price}} in HTML .
<input type="text" name="price" value="900" readonly="readonly" id="id_price">
Inside the same HTML i have a field to manually insert a quantity:
<input type="text" name="quantity" id="quantity">
And the final input to show to multiplication between those two
<input type="text" name="total" id="total">
As a script I used this (saw the answer in a question but i wasn't able to recreate the result in my "total" input)
SCRIPT
<script>
$(document).ready(function () {
$('').keyup(function () {
var multiplyAndShow = function () {
var val1 = parseFloat($('#id_price').val())
var val2 = parseFloat($('#quantity').val())
val3 = val1 * val2 || "Some Text"
$("#total").html(val3)
}
$("#id_price").keyup(function () { multiplyAndShow(); });
$("#quantity").keyup(function () { multiplyAndShow(); });
});
});
</script>
The script is not been used because when I set a quantity it doesn't make a thing in real time. The price value is readonly so i don't know if that's the problem.
I'm a newbie in javascript so any help will be appreciated
You should set the value of the total field, not the html. Change the following line
$("#total").html(val3)
to
$("#total").val(val3)
You should also change the $('') to $(document).
I'm trying to write a function with jQuery that will create a series of new inputs next to a series of unique inputs that already exist. The function should add event listeners to each of the new inputs so that whenever its value changes (something is typed into it, for example), the value of the original input next to it has the same value.
Eventually I will simply hide the original form so that the end user only sees the new form. I'm doing this for the sake of being able to control which parts of the form the user can see/modify and also to have more control over the way the form looks. The reason I have to do all this is because I have to do all this is because I'm modifying a Microsoft Sharepoint item creation form, and the only way to modify it is to add javascript to the page. If there's a better way of doing this I'm all ears. I'm relatively new to coding and very new to coding in Sharepoint.
Anyways, here's what I have:
var inputIdArr = [
'OrigInput1',
'OrigInput2',
'OrigInput3',
'OrigInput4',
'OrigInput5',
'OrigInput6',
'OrigInput7'
];
function newInputs(arr) {
for (str in arr) {
var elem = $( "[id='" + inputIdArr[str] + "']" );
var parent = elem.parent();
var newInputId = `newInput${str}`
var newInput = `<input type='text' id=${newInputId} />`;
parent.append(newInput);
$( `[id=${newInputId}]` ).change(function() {
console.log(newInputId + " changed");
elem.val($( `[id=${newInputId}]` ).value);
});
}
}
$(document).ready(function(){
newInputs(inputIdArr);
});
Currently, the console always logs "newInput7 changed". I'm not sure how to fix it so it logs that the correct new input has changed. I could also use guidance on where to go once that's done.
Programmatically keeping track of the generated ids of dynamically created elements is an anti-pattern that leads to needlessly verbose code and a maintenance headache.
Instead you can make the logic much more succinct and extensible by simply using classes and DOM traversal to group and relate elements to each other, something like this:
$('input.orig').after('<input type="text" class="appended" />');
$('#container').on('input', 'input.appended', function() {
$(this).prev('.orig').val(this.value);
})
.appended {
border: 1px solid #C00;
}
input {
display: block;
margin: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<input type="text" class="orig" />
<input type="text" class="orig" />
<input type="text" class="orig" />
</div>
Also note that using attribute selectors to find elements by id is redundant when the # id selector is available and much faster - even though it's not needed for this to work.
This should give you rought start,, I've created 7 original fields, and your function does new fields successfully. I've added event or binding on new fields outside of your loop because there was some issue I think.
// fields selection
var inputIdArr = [
'OrigInput1',
'OrigInput2',
'OrigInput3',
'OrigInput4',
'OrigInput5',
'OrigInput6',
'OrigInput7'
];
// function for creating new fields
function newInputs(arr) {
for (str in arr) {
var elem = $("[id='" + inputIdArr[str] + "']");
var parent = elem.parent();
var newInputId = `newInput${str}`
var newInput = `<input type='text' id=${newInputId} />`;
parent.append(newInput);
}
}
// create new inputs on dom ready
$(document).ready(function() {
newInputs(inputIdArr);
});
// bind new inputs and send value to org inputs
$(document).on('input', '[id^="newInput"]', function(el){
$(this).prev().val( $(this).val() );
});
input:nth-child(1){ border:1px solid red; }
input:nth-child(2){ border:1px solid blue; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><input type="text" id="OrigInput1"></div>
<div><input type="text" id="OrigInput2"></div>
<div><input type="text" id="OrigInput3"></div>
<div><input type="text" id="OrigInput4"></div>
<div><input type="text" id="OrigInput5"></div>
<div><input type="text" id="OrigInput6"></div>
<div><input type="text" id="OrigInput7"></div>
I am trying to populate a total field with id- #appointment-total_amount using javascript/jquery. Referring this Jsfiddle add two fields together - Which is working fine.
I am using this code in my _form.php
<?php
$script = <<<EOD
$(function() {
$('#appointment-doctor_fee').keyup(function() {
updateTotal();
});
$('#appointment-discount').keyup(function() {
updateTotal();
});
var updateTotal = function () {
var input1 = parseInt($('#appointment-doctor_fee').val());
var input2 = parseInt($('#appointment-discount').val());
$('#appointment-total_amount').text(input1 + input2);
};
});
EOD;
$this->registerJs($script);
?>
But nothing is happening on the page.
I am not able to see what I am missing here.
Thanks.
Related HTML
<div class="form-group field-appointment-doctor_fee">
<label class="control-label" for="appointment-doctor_fee">Doctor Fee</label>
<input type="text" id="appointment-doctor_fee" class="form-control" name="Appointment[doctor_fee]" maxlength="10">
</div>
<div class="form-group field-appointment-discount">
<label class="control-label" for="appointment-discount">Discount</label>
<input type="text" id="appointment-discount" class="form-control" name="Appointment[discount]" maxlength="10">
<div class="form-group field-appointment-total_amount">
<label class="control-label" for="appointment-total_amount">Total Amount</label>
<input type="text" id="appointment-total_amount" class="form-control" name="Appointment[total_amount]" maxlength="10">
The error is in this line:
$('#appointment-total_amount').text(input1 + input2);
Should be:
$('#appointment-total_amount').val(input1 + input2);
Besides that add at least simple check for illegal numbers, because you will get NaN if one of the fields is empty or input value is not valid number. Some range limit will be good too.
var updateTotal = function () {
var doctorFee = parseInt($('#appointment-doctor_fee').val());
var discount = parseInt($('#appointment-discount').val());
var totalAmount = doctorFee + discount;
if (isNaN(totalAmount) || totalAmount < 0 || totalAmount > 100000) {
totalAmount = '';
}
$('#appointment-total_amount').val(totalAmount);
};
One more error is in script registration. Change to this:
use yii\web\View;
$this->registerJs($script, View::POS_END);
Otherwise it will be inserted before jQuery (and your script depends on it) and will not be working.
Registering scripts that way is not good practice, it's even mentioned in official documentation. Separate file and using assets is definitely better than struggling with dependencies and inserting js as string (the errors are hard to detect, no autocomplete, etc.).
I'm trying to put together multiple user inputs and then combine them into one textarea after button click.
For example:
User1:Hey, I just met you
User2:And this is crazy
User3:But Here's my number so call me maybe
Combined Result:
Hey, I just met you, And this is crazy, But Here's my number so call me maybe
Here's my code the button click is currently not working but when I tried it before it did work so I was thinking I have some problem w/ my Jquery that triggers this unusual result:
HTML and Imports:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<input class="combine" id="input1" disabled="true"></input>
<input class="combine" id="input2" disabled="true"></input>
<input class="combine" id="input3" disabled="true"></input>
<input class="combine" id="input4" disabled="true"></input>
<input class="combine" id="input5" disabled="true"></input>
<input class="combine" id="input6" disabled="true"></input>
<input class="combine" id="Voltes5" disabled="true" size="45"></input>
<button id="setVal">Set</button>
Jquery
$(document).ready(function(){
$('#setVal').on('click',function(){
jQuery(function(){
var form = $('.combine');
form.each(function(){
$('.Voltes5').append($(this).text()+ ' ');
});
});
});
});
Update for sir Arun P Johny
User1: If theres a (no comma when combined)
User2: will
User3: there's a way
Combined Result:
If theres a will, there's a way
Try
$(document).ready(function () {
$('#setVal').on('click', function () {
var form = $('.combine').not('#Voltes5');
var vals = form.map(function () {
var value = $.trim(this.value)
return value ? value : undefined;
}).get();
$('#Voltes5').val(vals.join(', '))
});
});
Demo: Fiddle
Here's a one-liner for non-readability ;)
$('#setVal').click(function(){$('#Voltes5').val($('.combine').not('#Voltes5').map(function(){return $(this).val();}).get().join(''))});
Expanded:
$('#setVal').click(function(){
$('#Voltes5').val(
$('.combine')
.not('#Voltes5')
.map(
function(){
return $(this).val();
})
.get()
.join('')
);
});
Get fiddly with it: http://jsfiddle.net/ArtBIT/u57Zp/
Here is one way to do this:
$('#setVal').on('click', function () {
$(".combine[id^=input]").each(function () {
if(this.value) {
$("#Voltes5")[0].value += ' ' + this.value;
}
});
});
There are several different ways to do this..
I'd do it this way using an array:
$(document).ready(function () {
$('#setVal').on('click', function () {
//create an array for the values
var inpAry = [];
$('.combine').each(function () {
//add each value to the array
inpAry.push($(this).val+' ');
});
//set the final input val
$('#Voltes5').val(inpAry);
});
});
but you would need to remove the combine class from #setVal because that would be included in the .each.
This way it would also be possible to have the final box updated on keyup as I'm not just appending the values, the combined values are set each time.
$(document).ready(function(){
$('#setVal').on('click',function(){
var val='';
$('.combine').not('#Voltes5').each(function(){
val+=$(this).val();
});
$('#Voltes5').val(val);
});
});
.text() will give text of the element ,for input val u have to use .val()
So there's immediate big problem in the code, which is that you're referring to your Voltes5 element as a class, not an ID. The jQuery selector you want is:
#Voltes5
instead of:
.Voltes5
There are a few other things to think about too, though, for the sake of functionality and best practices. Firstly, the Voltes5 element also has class combine, meaning that the $('.combine').each() call will include this element. The outcome of this is that it will also append its current text to itself when the code is run (or, when the code is run with the above correction).
When grabbing the current entered text of an input element, a jQuery .val() call is what you want, not .text() - see this answer for some more discussion.
Another thing that could be noted is that you should really explicitly specify what sort of input these elements are; <input type="text"> is hugely preferable to <input>.
Finally, input is a void element (reading), meaning it shouldn't have any content between opening and closing tags. Ideally, you wouldn't even give a closing tag; either have just the opening tag, or self-close it:
<input>
<input />
HTH
replace $('.Voltes5').append($(this).text()+ ' ');
with
$('#Voltes5').append($(this).text()+ ' ');
Consider the following form:
<form>
<input type="button" value="Input Button"/>
<input type="checkbox" />
<input type="file" id="file"/>
<input type="hidden" id="hidden"/>
<input type="image" id="image" />
<input type="password" id="password" />
<input type="radio" id="radio" />
<input type="reset" id="reset" />
</form>
Utilizing Javascript (and jQuery), what would be the easiest way to clone the entire form and increment each individual id within, to ensure uniqueness.
Using jQuery I would assume you would clone the form initially via clone() and iterate through the cloned objects id and add the new id fieldname1, fieldname2 etc. However, my knowledge of jQuery isn't too great and this project is almost killing me.
Any help would be great!
You would clone() it, and before attaching the cloned element to the DOM, you'd run through and add the number to each id attribute.
(function() {
var count = 0;
window.duplicateForm = function()
var source = $('form:first'),
clone = source.clone();
clone.find(':input').attr('id', function(i, val) {
return val + count;
});
clone.appendTo('body');
count++;
};
})();
jsFiddle.
This one starts with 0, but you could easily start count with 1.
You could also use a closure if you wanted, i.e.
var cloneForm = function(form, start) {
start = start || 0;
return function() {
var clone = form.clone();
clone.find(':input').attr('id', function(i, val) {
return val + start;
});
start++;
return clone;
};
};
Then you would do...
var cloneContactForm = cloneForm($('#contact-form'), 5);
// Now I want to clone it and put it somewhere.
$(cloneContactForm()).appendTo('body');
jsFiddle.
Here's a solution without updating any ids:
Give all forms the same class
Give all fields a name
Refer to cloned forms relative to all the forms with the class
Refer to fields with their name
Example:
How about giving each cloned form a different id, and then using names for each input element?
<form class="theForm">
<input type="password" name="password" />
</form>
Then Clone it with
container.append($('.theForm:first').clone());
(or cache the first form in a variable).
Finally, access the input fields with:
$('form.theForm:eq(0) [name=password]') // password from first form
$('form.theForm:eq(1) [name=password]') // password from second form
...
If the selector lookup efficiency is a factor here then there are several trivial ways to speed it up, such as caching variables with the different forms, caching $('.theForm') and using the eq() method, etc.
Sample jsFiddle is here: http://jsfiddle.net/orip/dX4sY