I have a form, bunch of inputs and submit button. Some of the inputs are added and deleted dynamically. And some of them may be (or may not) disabled but I still need to get their values of the server.
So I have to add a handler to the button and collect the values of the disabled inputs manually and add them up to other, enabled. inputs. But I'd like not to go that way as it seems too complex (since some of the inputs are added / removed dynamically).
I can also add hidden inputs for each inputs which can be disabled but still it's a bit complex.
What I want is similar to 1. But instead of manually enumerating the enabled inputs by jquery selectors, I want to just get all values are being sent to the server at once by some jquery function maybe or by any other way. And then manually (by selectors) add up the values from the disabled inputs to them. Is this possible?
You could use the jQuery .serialize() for that.
The general structure of the function would look something like this
var mydata = $("#myform").serialize();
$.ajax({
type: "POST",
url: "ajaxurl",
data: mydata,
dataType: "json",
success: function(data) {
...
}
});
So I just figured you had a problem of how to get the disabled fields as well. You could use the function suggested in this thread:
Disabled fields not picked up by serializeArray
Just to make the answer complete, I will copy the plugin from there.
The usage is like this:
var data = $('form').serializeAllArray();
And here's the plugin itself:
(function ($) {
$.fn.serializeAllArray = function () {
var obj = {};
$('input',this).each(function () {
obj[this.name] = $(this).val();
});
return $.param(obj);
}
})(jQuery);
You could use a strategy like the following in your submit handler:
Select all disabled elements .. (don't lose the reference to these)
Enable all disabled elements
Serialize the form .. to get all the data
Disable the elements back
Submit your form.
Related
I have a small MVC5/C# Web application. In short, users will select a location from a dropdown ("#UnitList"). This fires the jquery event, to populate the next dropdown ("#CheckItem") with a list of contacts associated to the location selected.
Being very inexperienced in Jscript and Jquery, I am lost.
Additionally, on the same event, I need to populate an element (hidden text box).
In order to fill the hidden elements, I use this code
$(function () {
$("[name='UnitList']").change(function () {
$("#DeliveryUnitID").val($(this).val());
});
});
To run the Jquery that populates the second dropdown:
$(document).ready(function() {
$("#UnitList").change(function() {
var batchId = $(this).val();
var urlForModesl = getURLBase() + "ICS_Requisitions/Details";
urlForModesl = urlForModesl + "/" + batchId;
var modelsHtml = "";
$('#CheckItem')
.find('option')
.remove()
.end()
.append('<option value="Select Contact"></option>')
.val('Contact')
$.ajax({
type: 'get',
url: urlForModesl,
contentType: 'application/json',
dataType: 'json',
success: function(jsonData) {
$.each(jsonData, function(key, value) {
modelsHtml += "<option value='" + value.LoginID + "'>" + value.ContactName + "</option>";
});
$("#CheckItem").html(modelsHtml);
$("#DeliveryUnitID").val($(this).val())
},
error: function(XMLHttpRequest, textStatus, errorThrown) {}
});
});
});
I am aware that I have two functions with the same name "$("#UnitList").change(function ()" and that this is very bad and causing conflicts. This is what I am trying to resolve.
I have tried to simply add the element update within the Jquery code, but that did not work.
I placed the following code
$("#DeliveryUnitID").val($(this).val())
Inside the Jquery, right after:
$("#CheckItem").html(modelsHtml);
But that does not work. The hidden elements are still empty.
I tried creating a function called foo, with the element update, and call that function from at the end of the jquery.
foo();
<script>
function foo() {
$("#DeliveryUnitID").val($(this).val());
}
That also left the element #DeliveryUnitID empty.
I know that I can't have two functions with the same name, but that's the only way I can get it working where the query populates the drop down, and then the hidden element is populated too. BUT . . . that's bad coding AND, for about 5% of the users, it fails.
I can't quite figure out how to make both happen with one onchange event.
It's been a while since I've used jQuery, so here's what I'm seeing:
On change Event:
Get the value of the #UnitList <select> (potential bug: these aren't being stored anywhere)
Clear the options
Re-populate with new ones from AJAX Request
Try to get value of new options (still within initial AJAX request, which might also be a bug? Like I said, it's been a while since I've used jQuery).
It looks like you might have a state-management issue?
Potential fixes:
Store values of first dropdown before you clear them.
Use the stored value to populate #DeliveryUnitID after the AJAX request
Use some if statements or remove the event listener to not constantly be running your code on change event once you get the data you need...unless you need it to be running constantly.
To me, it would seem beneficial (from a code pov and maybe also a UX perspective) to programmatically build a second dropdown to keep things clearer, but that might be overkill for what you're trying to accomplish.
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 writing a script for a website I'm currently building.
var ownerForm = $('#item_owner_form_');
ownerForm.submit(function(ev) {
//$.ajax({
//'url': 'checklist_changeowner.php',
//'type': 'GET',
//'dataType': 'json',
//'data': {owner: blabla, item: blablbalba, checklist: blabla},
//'success': function() {
//
//}
//});
alert(ownerForm.serialize());
ev.preventDefault();
});
As you've probably already seen, I've set a fixed id for the ownerform (in this case #item_owner_form_) However, I am creating lots of forms through PHP and this is not what I'm looking for. For example, a form that will be generated could be identified as #item_owner_form_42 or as #item_owner_form_913.
Is there a universal character to make sure the ownerForm variable will use all of the forms that start with #item_owner_form_ ? Help would be much appreciated!
You class for that. It can be common for many(similar) elements.
So, your all forms would look like this,
<form id="item_owner_form_1" class="commonItemForm">
</form>
<form id="item_owner_form_2" class="commonItemForm">
</form>
And use the class in jQuery like this,
$('.commonItemForm').submit(function(ev) {
alert($(this).serialize());
ev.preventDefault();
// This function will get triggered for every form which has commonItemForm class.
});
I'm working on my first HTML form that performs an AJAX HTTP POST using jQuery. When a user makes a change to an input text field and tabs out of the field it triggers the AJAX script which in turn calls a PHP script which performs a database update.
I've got this working successfully for my first input field - I would now like to extend this to a 2nd, 3rd etc input fields but want to try and avoid having multiple scripts that perform very similar functions. I'm new to jQuery and AJAX so learning the syntax as I go.
Here's my input fields:
Manager
Phone
Here's my Javascript that is working on the storeManager input field:
<script type="text/javascript">
$(document).ready(function() {
$("#storeManager").change(function(){
var storeManager = $("#storeManager").val();
$.post('editProject.php', { storeManager: storeManager, id: '1E1DDA14-D2C6-4FC8-BA5F-DBCCC7ABAF7F' }, function(data) {
$("#managerRow").addClass("success");
}).fail(function () {
// no data available in this context
$("#managerRow").addClass("danger");
$("#ajaxAlert").addClass("alert alert-danger");
});
});
});
</script>
I essentially need to branch and pass an additional POST parameter to the editProject.php script so it knows which database field to update, and then conditionally add a class to the appropriate row.
Everything I've tried breaks the script when I try and get it to branch or pass a parameter based on the input field that is being edited. I haven't been able to find any examples that show the correct syntax to have the one script that is called by different input fields - I'm presuming this is possible instead of having multiple versions of the same script acting on different fields.
This works for multiple fields. Just call the same function from different input fields. I just broke your code into two parts.
1. onChange function of each individual field, and
2. function call by passing the field parameters.
<script type="text/javascript">
$(document).ready(function() {
$("#storeManager").change(function(){ yourFunction(this) }):
$("#worker").change(function(){ yourFunction(this) }):
$("#someX").change(function(){ yourFunction(this) }):
yourFunction(field)
{
var value = $(field).val();
var inputId=field.id;
$.post('editProject.php', { inputValue: value, id: inputId }, function(data) {
$('#'+inputId+'Row').addClass("success"); // (this looks like: *#storeManagerRow* ) you can change your Row id's accordingly to make your work easier. Eg: for **#storeManager** make this id as **storeManagerRow**
}).fail(function () {
// no data available in this context
$('#'+inputId+'Row').addClass("danger");
$("#ajaxAlert").addClass("alert alert-danger");
});
});
</script>
You just try to post a value. for example type. Which should contain some value for identify the ajax call.
If it is for login, then add type = 'login'. Then check the value of $_POST['type'] and write php according to it
sample.php
if(isset($_POST['type']))
{
if($_POST['type'] == 'login')
{
//your code goes here
}
}
you can use this kind of code :
$("#storeManager, #Manager, #Phone").change(function(){
You could do something like this using :input or a class that they all have
$(":input").on("change", function(){
var text = $(this).val();
var idOfInput = $(this).attr("id");
//your post to php function using the above variables
});
From this you could post the id of the input to your php script using the idOfInput variable which you could then on the php side use a case switch to do a different query depending on which id is sent to the php
Here is a jsfiddle showing how it works
I'm working on a site that allows users to love an item (like an item). The event is handled with jQuery and AJAX. The item array holds quite a lot of items and each item has a button to 'love'. I decided to efficiently reduce the number of forms on the page by putting one form at the bottom of the page and just submit it remotely.
So every time a user clicks the love button, the data attribute that holds the item id is put into the form and the form is submitted. Simple stuff.
But I'm finding the data response a bit more complex because I don't know how to find the element id of the item I want to update. I can't just use this or event.target because its inside a different event. I've also tried to carry the event parameter into the submit event, but it didn't work.
$(".love_item").click (event) ->
$(".love_item_item_id").val $(this).data 'id'
$(".love_item_form").submit()
$(this).hide(200)
$("form.love_item_form").submit (evt) ->
evt.preventDefault()
$form = $ #
$form.find(':submit').prop 'disabled', true
$.post($form.attr('action'), $form.serializeArray(), type: 'json').done (data) ->
$(event.target).parent().find(".item_info_box").html data
The last line, where it says event.target is as far as I've got. Its obvious that this variable is not carried, but I don't really know what to place there to achieve my goal. Also, I know that I could pass additional parameters through the form action (in other words send them to the rails controller and back), but I'd rather not. Any ideas?
You don't need an abitrary form at all. Something like this would work:
Example Markup (notice the data attribute):
Item to like
jQuery:
$('a.likeable').on('click', function() {
var $item = $(this);
var id = $item.data('id');
$.post('url/like/' + id, function() {
// success
// do something with $item here.
});
});
If you have an element like this: <div id="foo" data-id="foo1234">Foo</div>
You can select it after your ajax post like this, assuming you still have the ID of foo1234:
$('[data-id="' + id + '"]').doSomething();
Just use jQuery's ajax functionality
$('.love_item').on('click', function(e) {
$.ajax({
type: 'POST',
url: *insert url here*,
data: 'id=' + e.currentTarget.data-id,
success: function(response) {
var element = e.currentTarget;
// do whatever
}
})
});