I am new to KnockoutJS and I would like to serialize the current form, but when I console.log the serialized the form, it is empty.
How can I refer to the current form ?
Here is my DOM :
<form data-bind="submit: onSubmit">
<input type="text" data-bind="value: firstName">
<input type="text" data-bind="value: lastName">
<button data-bind="click: capitalizeLastName">Go caps</button>
<input type="submit" value="submit">
</form>
Here, the JS code :
$(document).ready(function () {
function AppViewModel() {
var self = this;
self.firstName = ko.observable("Bert");
self.lastName = ko.observable("Bertington");
self.fullName = ko.computed(function() {
return self.firstName() + " " + self.lastName();
}, self);
self.capitalizeLastName = function() {
var currentVal = self.lastName(); // Read the current value
self.lastName(currentVal.toUpperCase()); // Write back a modified value
};
self.onSubmit = function(form) {
// alert( self.firstName()) ;
console.log($(form).serialize()) ;
}
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
});
You are correctly referring to the current form in your code: it gets passed as the first argument to the submit data binding handler, however, only input with a name attribute are serialized by jQuery.serialize() method. Add name attributes to your fields and it will work.
From https://api.jquery.com/serialize/ (bold is mine)
Note: Only "successful controls" are serialized to the string. No
submit button value is serialized since the form was not submitted
using a button. For a form element's value to be included in the
serialized string, the element must have a name attribute. Values from
checkboxes and radio buttons (inputs of type "radio" or "checkbox")
are included only if they are checked. Data from file select elements
is not serialized.
However, I would advise you to follow #James Thorpe suggestion in the comments and get the form values from Knockout.js observables instead.
Related
I'm using serializeArray() to retrive the form attributes. When I try to get the attributes, I'm receiving name and value for all the fields.
I have checked the documentation https://api.jquery.com/serializeArray/. I understood it will return the name and value of all the fields.
Now I have few custom attributes for some fields. I want to retrieve them using those custom attributes.
How can i achieve this?
Here is my logic.
var data = $('form').serializeArray();
var newData = {};
var queue = {};
data.forEach(function(field) {
if( field.customField != undefined && field.customField.indexOf("true")>=0 ) {
queue[field.name] = frm.value
} else {
newData[frm.name] = frm.value;
}
});
I need to get that customField attribute, I'm adding that to the HTML field attribute.
May not be the best, but you can do like this.
Let's say you have set of text boxes, text areas and so on with custom data attributes in it. What I am doing here is adding a class to those fields that you need to get value / data attributes in it.
Let's take the following HTML as an example.
HTML
<form id="frm">
<input class="serialize" type="text" name="title1" value="Test title 1" data-test1="test AAA" data-test2="test BBB" /><br/>
<input class="serialize" type="text" name="title2" value="Test title 2" data-test1="test CCC" data-test2="test DDD" /><br/>
<textarea class="serialize" data-test1="textarea test 1">TEST 22 TEST 11</textarea>
<button id="btn" type="button">Serialize</button>
</form>
What I am doing here is iterating through fields which has class .serialize and putting value, name, data attributes and so on to an array.
jQuery
$(document).ready(function(){
$('#btn').on('click', function(e) {
var dtarr = new Array();
$(".serialize").each(function(){
var sub = new Array();
sub['name'] = $(this).attr('name');
sub['value'] = $(this).val();
//data attribute example
sub['data-test1'] = $(this).data('test1');
sub['data-test2'] = $(this).data('test2');
dtarr.push(sub);
});
// This will give you the data array of input fields
console.log(dtarr);
});
});
Hope this helps.
I'm using jquery autocomplete.In my case I have multiple autocomplete textbox and hidden field on my page.
e.g
<input class='myclass' type='text'> </input>
<input class='.emp_num_hidden' type='hidden'> </input>
<input class='myclass' type='text'> </input>
<input class='.emp_num_hidden' type='hidden'> </input>
and so on...
so when I fire change event on hidden field then it is raised multiple time
below is my code:
$(".myclass").each(function() {
var $empName= $(this);
var $empNumber = $empName.next('input:hidden');
//things to do
//Setting variable e.g url...
$empName.autocomplete(url,{
//code...
}).result(function(event,data,formatted)
{
$empNumber.val(formatted).change();
});
});
In above code $empNumber holds the hidden field which is used to store autocomplete value i.e in this case when
we select any text from autocomplete then that selected employees number will get store in hidden field.
Based on this hidden field value I want to do ajax call which will return full details of the employee based on his
employee number.
So I have written hanldler to change event of the hidden field as below.
$(.emp_num_hidden).on('change',function (
)};
here 'emp_num_hidden' is the class of the hidden field.
Please suggest how can I prevent multiple event on hidden field change.
This is done using the $(this) object. Since the change event has a target, it will only be effecting one element. The callback function is being executed on this element, this. For example:
$(".emp_num_hidden").on('change', function (e){
alert($(this).val());
});
What will happen is that an alert window will be shown when the hidden field is changed, containing the employee number from only that hidden field. You will also notices there are a few fixes to your code.
Personally, I would make use of both id and class attributes on your objects. This gives you wide scope and narrow scope to your selectors.
Example:
HTML
<input class='myclass' type='text' id='entry-txt-1' />
<input class='emp_num_hidden' type='hidden' id='hide-txt-1' />
<input class='myclass' type='text' id='entry-txt-2' />
<input class='emp_num_hidden' type='hidden' id='hide-txt-2' />
jQuery
$(function(){
var $empName, $empNumber;
$(".myclass").each(function(key, el) {
$empName= $(el);
$empNumber = $empName.next("input[type='hidden']");
// things to do
// Setting variable e.g url...
$empName.autocomplete(url, {
//code...
}).result(function(e, d, f){
$empNumber.val(f).change();
});
});
$(".emp_num_hidden").on('change', function(e){
var empId = $(this).attr("id");
var $employeeNumberField = $("#" + empId);
// Do the needful...
});
});
Taking this a bit further, you may want to consider making use of data attributes. You may also want to look at select event for Autocomplete. Something like:
$(function(){
$(".myclass").autocomplete({
source: url,
select: function(e, ui){
$(this).val(ui.item.label);
$(this).data("emp-number", ui.item.value);
$.post("employeedata.php", { n: ui.item.value }, function(data){
$("#empData").html(data);
});
return false;
}
});
});
This assumes that url returns an array objects with label and value properties. This would add the Employee Number as a data-emp-number attribute to the field that the user was making a selection from. The label being their Employee Name, and the value being their Employee Number. You could also use this callback to show all the other employee data based on Employee Number.
A working example: https://jsfiddle.net/Twisty/zmevd0r0/
I am trying to get the all form fields when user submits the form, the problem is with checkbox field that is when the checkbox is checked the name is submit to server but if this is unchecked then the checkbox is not submit to server, I am using knockout latest version Here is my working code:
<form data-bind="submit: submitForm">
<input type="checkbox" name="checkboxTest" data-bind="checked : value" />
<input type="text" name="textTest" value="Test" />
<button type="submit"> Submit</button>
</form>
And here is my ViewModel:
function viewModel(data)
{
self.value = ko.observable(true);
// when user submit the form
self.submitForm = function(fields)
{
var dataparams = $(fields).serialize();
// The form fields name are showing here
console.log(dataparams);
}
}
ko.applyBindings(new viewModel);
Could anyone tell me how to get the checkbox even if that is unchecked using knockoutjs, thank you in advance.
jQuery serializes the successful controls within the form.Only "successful controls" are serialized to the string. Values from checkboxes and radio buttons (inputs of type "radio" or "checkbox") are included only if they are checked which makes sense since they are a boolean state .If you want to have all inputs in your object you can add them manually.Or if you want to store value of true or false in your DB, instead of using checkbox you can use <select> with the value of 0 and 1 (YES ,NO)
Here's an example:
HTML:
<form data-bind="submit: submitForm, with: form">
<input type="checkbox" name="checkboxTest" data-bind="checked : value" />
<input type="text" name="textTest" value="Test" />
<button type="submit"> Submit</button>
</form>
JS:
function viewModel() {
this.value = ko.observable(true);
}
function parentViewModel() {
var self = this;
self.form = ko.observable();
// when user submit the form
self.submitForm = function() {
var dataparams = ko.toJSON(self.form);
// The form fields name are showing here
console.log(dataparams);
};
}
var vm = new parentViewModel();
vm.form = new viewModel();
ko.applyBindings(vm);
Then you should get the properties in JSON. In this case, either {"value": true} or {"value": false}
Working example
I have a checkbox in a form that acts as a flag.
In order to do it, I added a hidden input element so that if the checkbox is not checked, something will still be saved
<form action="">
...
<input type="hidden" name="foo" value="no" />
<input type="checkbox" name="foo" value="yes">
...
</form>
The problem I am having is that when I
check the checkbox
then run jQuery.serializeArray() on the form
the value set for the foo element is "no"
Object { name="foo", value="no"}
Shouldn't serializeArray() emulate browser behaviour? If so, shouldn't it return "yes" if checkbox is checked?
I am using jQuery v1.10.2
In a short word: No. The serializeArray method only returns the checkbox in the case it is checked. Thus, it will ignore it as long as it remains unchecked.
In case you checked it, though, it wiill return the value of your input directly.
Check out the demo at http://api.jquery.com/serializearray/ .
Using serializeArray on a form with multiple inputs of the same name returns more than one object for each element (if checked). This means that the following HTML will return the following object. So the data in question is there and is available. Because of this I'm assuming that you're attempting to either manipulate the data to be in 1 object or you're posting it to a server which is only taking into account the data from the first value with that key. You just need to make sure that any checkbox element takes precedence.
Returned Object:
[
{
name:"foo",
value:"no"
},
{
name:"foo2",
value:"no"
},
{
name:"foo2",
value:"yes"
}
]
HTML:
<form>
<input type="hidden" name="foo" value="no" />
<input type="checkbox" name="foo" value="yes" />
<input type="hidden" name="foo2" value="no" />
<input type="checkbox" name="foo2" value="yes" checked />
</form>
JS:
console.log($('form').serializeArray());
DEMO
Another way you can do this is get rid of the hidden fields and before you submit the form go through each unchecked checkbox and check if there is any data in the serializeArray with the same name. If not just add it in there as a off.
$('#submit').on('click', function(){
var arr = $('form').serializeArray(),
names = (function(){
var n = [],
l = arr.length - 1;
for(; l>=0; l--){
n.push(arr[l].name);
}
return n;
})();
$('input[type="checkbox"]:not(:checked)').each(function(){
if($.inArray(this.name, names) === -1){
arr.push({name: this.name, value: 'off'});
}
});
console.log(arr);
});
DEMO
Using the same name for multiple fields is problematic at best and there is no standardized way that front end systems, or back end systems, will handle it.
The only reason to use the same name is if you are trying to pass some kind of a default value, like you are in the case below, where you are doing a simple yes/no.
What you want, to emulate the browser, is serialize method, not the serializeArray.
I added the form to a page -- from my console:
JSON.stringify(f.serializeArray());
"[{"name":"foo","value":"no"}]"
NO checkmark
JSON.stringify(f.serialize());
""foo=no""
Checkmark
JSON.stringify(f.serialize());
""foo=yes&foo=no""
If your back end system gets confused and is picking up the wrong value, reverse the order of your checkmark and hidden element.
FACT: jQuery serializeArray() does not include unchecked checkboxes that probably we DO need them sent to server (no problem for radios though).
SOLUTION: create a new serialize:
//1. `sel` any collection of `form` and/or `input`, `select`, `textarea`
//2. we assign value `1` if not exists to radios and checkboxes
// so that the server will receive `1` instead of `on` when checked
//3. we assign empty value to unchecked checkboxes
function serialize(sel) {
var arr,
tmp,
i,
$nodes = $(sel);
// 1. collect form controls
$nodes = $nodes.map(function(ndx){
var $n = $(this);
if($n.is('form'))
return $n.find('input, select, textarea').get();
return this;
});
// 2. replace empty values of <input>s of type=["checkbox"|"radio"] with 1
// or, we end up with "on" when checked
$nodes.each(function(ndx, el){
if ((el.nodeName.toUpperCase() == 'INPUT') && ((el.type.toUpperCase() == 'CHECKBOX') || (el.type.toUpperCase() == 'RADIO'))){
if((el.value === undefined) || (el.value == ''))
el.value = 1;
}
});
// 3. produce array of objects: {name: "field attribute name", value: "actual field value"}
arr = $nodes.serializeArray();
tmp = [];
for(i = 0; i < arr.length; i++)
tmp.push(arr[i].name);
// 4. include unchecked checkboxes
$nodes.filter('input[type="checkbox"]:not(:checked)').each(function(){
if(tmp.indexOf(this.name) < 0){
arr.push({name: this.name, value: ''});
}
});
return arr;
}
The reason we assigned empty string to unchecked checkboxes is because a checked one will submit it's value to server which is set in html and can be a zero!!!
So, an empty value denotes a unchecked checkbox.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<form url="http://application.localdev/api/v1/register" method="post" id="formReg" accept-charset="utf-8">
<input type="email" placeholder="email" name="email"><br>
<input type="text" placeholder="firstname" name="firstname"><br>
<input type="text" placeholder="lastname" name="lastname"><br>
<input type="number" placeholder="zip_code" name="zip_code"><br>
<input type="checkbox" name="general" value="true"> general<br>
<input type="checkbox" name="marketing" value="true"> marketing<br>
<input type="checkbox" name="survey" value="true"> survey<br>
<button type="submit">save</button>
</form>
<script>
$(document).ready(function() {
$('#formReg').on('submit', function(e){
// validation code here
e.preventDefault();
var values = {};
$.each($('#formReg').serializeArray(), function(i, field) {
values[field.name] = field.value;
});
$('input[type="checkbox"]:not(:checked)').each(function(){
if($.inArray(this.name, values) === -1){
values[this.name] = $(this).prop('checked')
}
});
console.log(values)
});
});
</script>
serializeArray doesn't return unchecked checkbox. I try this instead of serializeArray:
$('input, select, textarea').each(
function(index){
var input = $(this);
alert('Type: ' + input.attr('type') + 'Name: ' + input.attr('name') +
'Value: ' + input.val());
}
);
Help me please:
I have a dynamic part of a module (generated by php application), for example:
<input type="text" class="attr" name="Input_0"/>
<input type="text" class="attr" name="Input_1"/>
...
<input type="text" class="attr" name="Input_n"/>
The value n is random (n> = 1). Obviously at the bottom of the form there's a submit button that confirms the completion of fields.
So, I need a procedure to read the modified values of the input tag via jquery script that gives this output:
Input_1 = value
Input_5 = value
...
Input_n = value
How can I do this?
here is some sample code :
var $inputs = $('#form_id :input');
var values = {};
$inputs.each(function() {
values[this.name] = $(this).val();
});
Try serializing the form data and looping through the inputs and their values:
$('form').submit(function(e) { // when we submit the form
e.preventDefault();
// loop through form data and print values
var data = $.each($(this).serializeArray(), function(i, value) {
console.log(value);
});
});
Check out this fiddle: http://jsfiddle.net/kukiwon/ECz52/