I am trying to use Javascript/jQuery to get data from a form and save the value to a variable. There is only a single text input and submit button in the form, and only one piece of data will need to be retrieved. I pieced together this code from examples online but it isn't giving me any output.
$("#submit").onclick = function() {
var input = "";
$("#binary-input").click(function() {
var x = $("form").serializeArray();
$.each(x, function(i, field) {
input = field.value;
});
});
console.log("Input: ");
console.log(input);
}
A fix for my code is what I'm requesting, but a more efficient approach would also be much appreciated.
First off jQuery doesn't have an 'onclick' event handler. You can either use 'click' (https://api.jquery.com/click/) like so:
$("#submit").click(function()...
Or use 'on' (https://api.jquery.com/on/) and specify the type of event you want to handle
This is what I'd normally do:
$("#submit").on("click", function(){
// Get the input and its value
var inputValue = $("#binary-input").val();
// Output the value
console.log(inputValue);
}
Hope that helps.
I am using a backend where it is ideal that I send an ajax post request rather than using the default action on forms.
With this in mind, I need to extract the final fields that are selected in my form.
I have various text fields, radio buttons, checkboxes, etc.
I've always struggled gaining a good understanding of event delegation and event propagation. I'm not entirely sure if this is the topic I should be worried about with what I am trying to achieve.
I know I can write code that grabs all of the information in my form by placing an ID on each field and a have a function extract each value on the ID such as:
function example(){
var field0 = $('#field0').val();
var field1 = $('#field1').parent().hasClass('active')
// ... and more
}
I've used this pattern for a while and I don't feel like it is efficient.
I have two pattern idea, but I am still not sure if this is a "common practice"
Since I am not concerned about the data in each field until the form is submitted, I could run a loop on all of my input based fields on my form and extract the contents, instead of assigning an ID to each individual input field.
I can listen to changes on the form (I am not exactly sure how to do this, this is where event delegation/propagation will come into play). Instead of waiting for the submit button to gather all the info in the form, I will have some type of listener that detects a change on the form (not sure if that is possible).
I've been using my current pattern for several months and would like to improve myself, If anyone has any suggestions, links, or criticism about my thoughts on a new approach I'd appreciate it.
So, you basically propose 3 ways to get all form fields with a value on submit (or a similar event):
hard-code IDs and retrieve their values, e.g.
var field_a = document.getElementById('a')
, field_b = document.getElementById('b')
, form = document.getElementById('my_form');
form.addEventListener('submit', function() {
fetch('//your/api/endpoint', {
method: 'POST',
body: JSON.stringify({a: field_a.value, b: field_b.value})
});
});
loop all and retrieve their values, e.g.
var form = document.getElementById('my_form');
form.addEventListener('submit', function() {
var values = [].reduce.call(
form.querySelectorAll('input, textarea, select'),
function(values, element) {
values[element.name] = element.value;
return values;
},
{}
);
fetch('//your/api/endpoint', {
method: 'POST',
body: JSON.stringify(values)
});
});
watch for changes inside the form, accumulate them
var form = document.getElementById('my_form')
, state = {};
form.addEventListener('change', function(e) {
state[e.srcElement.name] = e.value;
});
form.addEventListener('submit', function() {
fetch('//your/api/endpoint', {
method: 'POST',
body: JSON.stringify(state)
});
});
From a performance perspective, option 1. will be the fastest, followed by 2 followed by 3 (with the last 2 I'm not 100% certain, querySelectorAll can be expensive, but listening for tons of change events might be as well -- depends on how often change events are triggered I'd say).
From development perspective (how long does it take to set up a form), 2 and 3 should not be that different as they are both generic (and you can use my code sample as a start).
"Real" data-binding (like Angular) or "pure state" (like React) pretty much come down to options 2/3 as well (just that the framework will perform the heavy lifting for you).
Regarding option 3 (listening for a change on the whole form): https://stackoverflow.com/a/4616720/1168892 explains quite well how event bubbling in JavaScript happens. To use that you have to make sure that no element inside the form cancels the change event (otherwise it would not bubble to the form itself). To not cancel events is the default behavior, so you would have to explicitly make this wrong (and with that you can just have an eye on it in your implementation).
I didn't use jQuery in my examples as that can all be done by browsers directly now. What I used are Element.querySelectorAll, Array.reduce and window.fetch.
Pattern #1 (use serializeArray)
$('#formId').on('submit', function(e){
var allData;
e.preventDefault();
allData = $(this).serializeArray();
// use the allData variable when sending the ajax request
});
Pattern #2 (use the delegated form of $container.on('event', 'selector', ..) and the change event)
$('#formId').on('change', 'input,textarea,select', function(){
var element = $(this), // element that changed
value = element.val(); // its new value
// do what you want ..
});
Without jquery I once wrote a function that return in an object all input value tie with its name.
I think it's better than plain id link, because you don't have to worry about what's inside your form, as long as your giving a name attribute to your inputs.
function getFormData(form) {
var data = {};
for (var i = 0; i < form.elements.length; i++) {
var input = form.elements[i];
if (input.value && input.type !== 'submit' && input.type !== 'button') {
data[input.name] = input.value;
}
}
return data;
}
All you need to do is passing your form like this:
var form = document.querySelector('.monFormulaire');
// your form data
var data = getFormData(form);
I'm trying to use jQuery for email validation in a form field
$(document).ready(function() {
var email = new RegExp("[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$");
var value = $("#email_address").val();
$("#email_address").on("keypress", function() {
if(email.test(value)) {
$("#email_address").parent().addClass("has-success");
}
});
});
However, the has-success class doesn't get added. I've tried each line of code individually in the console and they all seem to be doing/pointing to the right thing. It's when it's all put together that it doesn't seem to work.
You load the value on jQuery's DOM ready and never load it again.
You need to test the current value, not the one that's there when the DOM is ready, roughly:
$("#email_address").on("keypress", function() {
if(email.test($(this).val())) {
$("#email_address").parent().addClass("has-success");
}
});
Unrelated, but personally I'd wrap up the email test in a function so instead of saying email.test(xxx) you could read it more naturally like validEmail(xxx) etc.
I have a jquery jhtml WYSIWYG editor in a form and I need to append its output to a textarea manually. The form is being submitted via ajax. The updateText function is called to grab whats in the wysiwyg div and place it in a textarea to enable ajax to send it. I am using the ajaxForm “beforeSubmit” callback to fire off this function.
//For Ajax Form
$('#addFaci').ajaxForm({
beforeSubmit: updateText,
success: function(response) {
eval(response);
}
});
function updateText(formData, jqForm, options){
var save = '#detail';
$(save).val($(save).htmlarea("toHtmlString"));
return true;
};
This is not working on the first submit... you have to click submit twice before updateText actually fires. Does anyone have any ideas?
Thanks,
When you hit submit this is what happens:
Form data is being collected
beforeSubmit fires, and the collected form data is being passed as the first parameter
You're changing the value of textarea, but it's too late, because data has been already collected
Instead of changing textarea's value you should modify formData object.
UPD. Try this:
for (var i in formData) {
if (formData[i].name == '...name of your textarea here...') {
formData[i].value = ...wysiwyg's html...
}
}
Even easier, remove the hidden textarea and use this:
function updateText(formData, jqForm, options) {
formData.push({name: 'textarea_name', value: .... })
return true;
};
I get this.refresh() is not a function in the error log every time I use this function but it works fine.
Also, when I click on this function for the first time, this.value=undefined. When I click the function again in this form and every other form, the value populates just fine with the previous value.
What could I be doing wrong?
How do I write this function more efficiently?
I still don't quite understand how to use this.value to capture and store a value within an array.
function askGender(x) {
response = "<select class=widgetstyle onClick=_setGender(this.value)><option value=Female>Female<option value=Male>Male</select>";
characters[x].setGender(response);
if (this.gender != 0) {
response = this.gender;
this.gender = 0;
characters[x].setGender(response);
}
}
function _setGender(x) {
this.gender = x;
this.refresh();
}
response = "<select class=widgetstyle onClick=_setGender(this.value)><option value=Female>Female<option value=Male>Male</select>";
look at your response. You set the gender in the click handler. Your misunderstanding on how this works.
this in askGender refers to your character object. When the onClick handler get's called this will refer to the DOM object in your setGender method.
For the record .refresh is a method of his Character object.
The entire code is large and requires thorough debugging. It looks like your editing open source code and trying to use it in a way it was not designed to be used.