I'm working on an online application that uses a lot of forms like this:
<form action="..." id=".." method="post">
<label for="i0">something</label>
<input type="text" id="i0" .... />
<label for="i1">something</label>
<select id="i1"..> <option>a</option> <option>b</option> </select>
.....
<input type="submit" ...>
</form>
I use some JQuery plugins to serialize and deserialize data so I can save all data to database in one JQuery line and fill form with another instruction. My problem now is that in some context I need to show only the data, not editable form.
The question is: is there any JQuery plugin or some code that converts a <form> into a textual data preserving the form structure?
Note: a simple option is to show the form and disable all form fields, but this is not a good option if the user wants to print the data.
var html = '';
var $form = $('#form');
$form.find('label').each(function() {
var $label = $(this);
html += '<p>' + $label.text() + ': ' + $('#' + $label.attr('for')).val() + '</p>';
})
$form.replaceWith('<div>' + html + '</div>');
If you're doing that on submit, you could use jQuery form plugin and the formSerialize() function or beforeSubmit() callback.
var queryString = $('#myFormId').formSerialize();
or
$("#myFormId").ajaxForm({
beforeSubmit: function(arr, $form, options) {
// The array of form data takes the following form:
// [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
// return false to cancel submit
return true;
},
success: function() {
//success (your actions here)
}
});
(Use $form).
Here is non-jquery crossbrowser workaround:
var getOuterHtml = function(node){
var wrapper = document.createElement('div');
document.body.appendChild(wrapper);
var clone = node.cloneNode(true);
wrapper.appendChild(clone);
var result = wrapper.innerHTML;
document.body.removeChild(wrapper);
return result;
};
Here is working example.
P.S. By the way in ie you can use node.outerHTML.
EDIT: little bit modified example so that it wouldn't remove original form
I would propose a little different, but seems more appopriate solution - jQuery Templates
You keep you common code as template, depending on actual needs, you wrap those templates either to <forms> or <div>. This is more clear and easy to support.
Related
I have some input in my form,now I want to get the json object from the form without some input named point,What's wrong with my code?I have to remove them.It seems not work for not() function.How to fix my code?
<form id="myform">
<input name='student' value='a'/>
<input name='student' value='b'/> '
...
<input name='point' value='90'/>
<input name='point' value='95'/>
</form>
Now I only want to submit the student data to the server.So I write the code:
var data = $('#myform').not("input[name='point']").serializeArray();
var objParam = {};
$.each(data, function(i, v) {
objParam[v.name] = v.value;
});
but the result still have point data.What's wrong with not() function?
breaking down your code $('#myform') selects your form, in this case, only one object, then you filter that object with .not("input[name='point']") but there is only one object which is the form itself.
You want to filter the form's children instead, so just add .children() like this:
var data = $('#myform').children().not("input[name='point']").serializeArray();
var objParam = {};
$.each(data, function(i, v) {
objParam[v.name] = v.value;
});
Hope this will help you.
$('#myform input[name!=point]').serializeArray()
Your selector is faulty.
$('#myform').not("input[name='point']").serializeArray()
...says, "Serialise the form with ID 'myForm' which is not also an input and has the name 'point'.
Rather, you mean: "Serialise the form with ID 'myForm' but omit its child inputs with name 'point'.
Here's a non-jQuery way, using native FormData.
//get the form as form data
var fd = new FormData(document.querySelector('#myform'));
//delete any elements pertaining to [name=point]
fd.delete('point');
//et voila; this shows we retain only the student fields
for (var key of fd.keys()) alert(key);
Can I know that how to get updated json file for the newly entered form input fields. As of now, I can able to save my form input fields into my json file, but if I enter any new input value then if I hit my Save button, then this newly entered values are not storing into my json file(I can still see my old key/values). Please let me know where I'm doing wrong and how to do this ?
html:
<form id="imagesId">
<input type="hidden" value="/images/Image1.png" name="Image1">
<input type="hidden" value="/images/Image2.png" name="Image2" >
<input type="hidden" value="/images/Image3.png" name="Image3">
<input type="hidden" value="/images/Image4.png" name="Image4">
<input type="hidden" value="/images/Image5.png" name="Image5">
<input type="button" id="submitButton" value="Save">
</form>
json:
[{"name":"Image1","value":"/images/Image1.png"},{"name":"Image2","value":"/images/Image2.png"},{"name":"Image3","value":"/images/Image3.png"},{"name":"Image4","value":"/images/Image4.png"},{"name":"Image5","value":"/images/Image5.png"}]
jQuery:
$("#submitButton").on('click', function(e) {
var jsonToSave = $("#imagesId").serializeArray();
var jsonData = JSON.stringify( jsonToSave );
var $downloadAnchor = $("<a/>", {
href: 'data:text/json;charset=UTF-8,' + jsonData,
download: "Image.json"
});
$downloadAnchor.text("Click here to download JSON");
$("#imagesId").append($downloadAnchor);
e.preventDefault();
return false;
});
The problem was that $downloadAnchor holds a reference to a DOM element (a jQuery object = a DOM element wrapped in $()). When you append that element to the DOM, $downloadAnchor still refers to that same object. It doesn't magically duplicate it when you want to insert it again into the DOM, unless you .clone() it.
What you need do is to check if that anchor (thru it's ID/class) is already in the DOM, if yes, just update it's href with the new data as below.
$("#submitButton").on('click', function(e) {
e.preventDefault();
var $form = $("#imagesId");
var jsonToSave = $form.serializeArray();
var jsonData = JSON.stringify(jsonToSave);
var $downloadLink = $("#download");
if ( $downloadLink.length ) {
$downloadLink.attr({
'href': 'data:text/json;charset=UTF-8,' + jsonData
});
} else {
$form.append(
$("<a/>", {
'href': 'data:text/json;charset=UTF-8,' + jsonData,
'download': "Image.json",
'id': 'download',
'text': "Click here to download JSON"
})
);
}
});
A demo for the above.
Edit: To be able to append each file uploaded as an input (with a unique name + value of the uploaded file) to the form, you need to do 2 things.
Bind a change handler to the file input, if a file is uploaded (meaning, not just a click and cancel on the file upload dialog), append it to the form as an input with the file as the value (after whatever find/replace you want to do).
The click handler on the $("#submitButton") would only take in all the inputs, serialize them and then create/modify the download anchor link as in my first code attempt.
Here is a demo for the above (the edit part).
var $form = $("#imagesId"); //The form
var len = $form.find('input[type="hidden"]').length; //Number of files in the form
$form.on("change", ":file", function() {
var file = $(this).val() || false;
if (file) {
//Do your replace etc. here
//.replace(/C:\\fakepath\\/i, '');
len++;
$form.append('<input type="hidden" value="' +file+ '" name="image' +len+ '" />');
}
});
$("#submitButton").on('click', function(e) {
e.preventDefault();
var jsonToSave = $form.serializeArray();
var jsonData = JSON.stringify(jsonToSave, null, 4);
var $downloadLink = $("#download");
alert (jsonData);
//Other code goes here such as create anchor, append/modify etc.
});
Link to the demo for the edits above.
You Can use push like this
oldJson.push(newJSon);
I'm using Knockout JS on a form that's used to calculate pricing for a product.
I have a function that is called on form submit and calculates pricing. For the text input fields, I'd like for the pricing function to be called as soon as user starts changing values. At the moment this only works if I click outside of the text input field, so not immediately on keypress/keyup, which is what I'd like to achieve.
I'm pretty sure it's something in my code that needs fixing.
HTML for the input field:
<div class="form-group">
<label>Number of Pages</label>
<input data-bind="value : pages, valueUpdate: ['afterkeydown'], event: { change: onSubmit }" >
</div>
Javascript:
self.pages = ko.observable("10");
self.onSubmit = function () {
self.response("<div class='priceLoading'>Loading</div>");
var servURL = "http://prices.mysite.com/getpricing/"
+ ko.utils.unwrapObservable(self.selectedCategoryValue) + "/"
+ self.pages() + "/"
+ self.copies()
$.get(servURL, function (response) {
self.response(response.PriceFormatted);
})
}
The onSubmit function that is called on the event change grabs data xml data from a service and writes it on the form.
Any help with this greatly appreciated!
You can use
<input data-bind="textInput : pages, event: { keyup: onSubmit }" >
It makes a little more sense, if you want to submit on every change to your variable, to subscribe your onsubmit function to the variable rather than having a separate event.
var self = {};
self.pages = ko.observable("10");
self.response = ko.observable();
self.copies = ko.observable("5");
self.pages.subscribe(function(newValue) {
self.response("<div class='priceLoading'>Loading</div>");
var servURL = "http://prices.mysite.com/getpricing/" + ko.utils.unwrapObservable(self.selectedCategoryValue) + "/" + self.pages() + "/" + self.copies()
setTimeout(function() {
self.response("Fetched for " + newValue);
}, 500);
});
ko.applyBindings(self);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class="form-group">
<label>Number of Pages</label>
<input data-bind="value : pages, valueUpdate:'afterkeydown'">
<div data-bind="text:response"></div>
</div>
I'm using select2() field using select2 library and Drag and Drop Sorting is enabled in the field.
It works well, but once i save it, the ordering break and they are ordered alphabetically.
I was wondering if its possible to anyhow save ordering of elements after drag drop in select2() fields.
Please suggest.
Per Select2 documentation, the new ordered values are saved in a attached hidden field.
http://ivaynberg.github.io/select2/
(right click on the Input field and then inspect element to find the line below just after the div#select2-container)
There are two options that might work for you:
Option 1:Easy one
Check the ordering of how you are feeding the control, specific on:
$("#e15").select2({tags:["red", "green", "blue", "orange", "white", "black", "purple", "cyan", "teal"]});
The control just render the same order that the above line is specified.
If you are not saving those values as comma separated text and instead as row records, maybe your database query is ordering them alphabetically.
Option 2: A little bit further
This code will serve you to save the ordered values in a cookie, so you can have the same order within your whole session.
$(function(){
if ($.cookie('OrderedItemList') != null){
$("#e15").select2({tags: $.cookie('OrderedItemList').split(',')});
}
$("#e15").on("change", function() {
$("#e15_val").html($("#e15").val());
$.cookie('OrderedItemList', $("#e15").val(), { expires: 365 });
});
});
Please note, this code might not work for database bound fields, you might need to add some code if thats what you need.
Well I had your problem. I've overcome it with something like this...
A hidden input to save your order.
the listener on the select2.
$("#reports").on('change', function(){
var data = $(this).select2('data');
var array = [];
$.each(data, function(index, val) {
array[index]=val.id;
});
array.join(',');
$("input[name=reports]").val( array );
});
<form class="form-horizontal form-bordered" action="#something" method="post" accept-charset="utf-8" target="_blank" >
<input type="text" name="reports" >
<select id="reports" class="form-control select2me" multiple >
<? foreach ($Balance::getSeparators() as $key => $value ) { ?>
<option value="<?=( $key )?>"><?=( $value )?></option>
<? } ?>
</select>
</form>
This way the input[name=reports] sends to your page the correct order.
Select2 has progressed to version 4, which is based on <select/> and <option/>-tags, instead of <input/>-tags. I solved it for version 4 as follows:
$(".select2").select2().on('select2:select', function(e){
var $selectedElement = $(e.params.data.element);
var $selectedElementOptgroup = $selectedElement.parent("optgroup");
if ($selectedElementOptgroup.length > 0) {
$selectedElement.data("select2-originaloptgroup", $selectedElementOptgroup);
}
$selectedElement.detach().appendTo($(e.target));
$(e.target).trigger('change');
})
Basically I remove and re-add the selected items to the select-options-list, so that they appear in order of selection.
The hidden field solution was a good solution in my case, but Select2 plugin still keep a numerical/alphabetical(?) order, that is not the user selection's order
I found a solution, that solves all my needs.
In my symfony form declaration will be the hidden field called selectOrder in which to save the current order:
$("#form_people").on('change', function(){
var data = $(this).select2('data');
var array = [];
$.each(data, function(index, val) {
array[index]=val.id;
});
array.join(',');
$("#selectOrder").val( array );
});
and in the javascript part after form declaration there is my Multi Select2:
var sel = $("#form_people").select2({
maximumSelectionSize: 3,
minimumInputLength: 1,
escapeMarkup: function(m) { return m; },
});
then
//After reloading page you must reselect the element with the
//right previous saved order
var order = $("#selectOrder").val().split(",");
var choices = [];
for (i = 0; i < order.length; i++) {
var option = $('#form_people option[value="' +order[i]+ '"]');
choices[i] = {id:order[i], text:option[0].label, element: option};
}
sel.select2('data', choices);
It's what I need, and maybe can help other developers
Is there a certain or special of dealing with hidden fields in jQuery? I am using a hidden input field and am not receiving a value. Obviously, my code is incorrect and would be grateful if someone could show me the error. many thanks
<input id="customer" name="customer" type="hidden" value="<?php echo $_SESSION['kt_idcode_usr']; ?>" />
$('#submit').click(function () {
var name = $('.uname').val();
var customer = $('.customer').val();
var department = $('#department').val();
var email = $('.email').val();
var position = $('.position').val();
var feedback = $('.feedbacknew').val();
var data = 'uname=' + name +
'&customer=' + customer +
'&department=' + department +
'&email=' + email +
'&position=' + position +
'&feedbacknew=' + feedback;
$.ajax({
type: "POST",
url: "feedback.php",
data: data,
success: function (data) {
$("#feedback").get(0).reset();
$('#message').html(data);
//$("#form").dialog('close');
$("#flex1").flexReload();
}
});
return false;
});
$('.customer').val(); ???
not ., #
result
$('#customer').val(); // works
try changing
var customer = $('.customer').val();
to
var customer = $('#customer').val();
you don't have such a class customer anywhere in this code
This line of code is wrong
var customer = $('.customer').val();
you have defined your hidden field by id, not by class, so you would need to use a # instead of a . on the selector
var customer = $('#customer').val();
The line you have here:
var customer = $('.customer').val();
...is looking for elements with a class called "customer". You don't have any such element. You have an element with an id of "customer". I suspect it will work if you simply change this line to:
var customer = $('#customer').val();
I'd suggest doing this for the rest of your input fields as well. Generally you'll want to identify them by id when collecting values to submit the form. Identifying them by class is typically more for things like styling different kinds of fields, binding event handlers, and so on.
note the difference:
alert($('.customer').val());
and
alert($('#customer').val());
. is for classes, see http://api.jquery.com/category/selectors/
I can see that for customer you are using jquery selector ".customer" which searches for an element with class name "customer" but your input has id equal to this, so:
var customer = $('#customer').val();
may I suggest serialize()?