For submitting the form data to the server from the AJAX call to bind Telerik MVC grid, we can set e.data in OnDataBinding event to a anonymous JavaScript object
<script type="text/javascript">
function Grid_onDataBinding(e) {
var categoryValue = "Beverages";
var priceValue = 3.14;
// pass additional values by setting the "data" field of the event argument
e.data = {
// the key ("category") specifies the variable name of the action method which will contain the specified value
category: categoryValue,
price: priceValue
};
}
</script>
To facilitate the model binding for Boolean, ASP.NET MVC generates checkboxes along with a hidden text field with the same name
<input name="myCheckBox" class="check-box" id="myCheckBox" type="checkbox" CHECKED="checked" value="true"/>
<input name="myCheckBox" type="hidden" value="false"/>
and when these are submitted the data submitted is
myCheckBox=true&MyCheckBox=false - when the checkbox is checked
myCheckBox=false - when the checkbox is not checked
For pages where there is no checkbox, the post data can be easily obtained by
e.data = form.serializeObject()
where serializeObject creates that object by looping thru all the form fields. How to construct that object in case of forms when there are checkboxes as described above? Basically how can a name-value pair list be represented in the object form when the names are allowed to be duplicate?
e.data = {
textBox1: "some value1",
myCheckBox: true //,
//myCheckBox: false // ???
};
The implementation of serializeObject creates an array for such form elements and those are submitted as myCheckBox[]=true&myCheckBox[]=false which breaks the model binding on the server side.
You can select specific form subelements to serialize, rather than just serializing the entire form. This allows you to filter out the ones you don't want:
$('form input:not([type=hidden])').serializeObject();
Edit: Per #amit_g's comment, you want the checkbox when it's checked or the hidden element when it's not. This requires a more complex filter than the :not selector:
$('form input')
.filter(function() {
if ($(this).attr('type') == 'hidden') {
// filter out those with checked checkboxes
var name = $(this).attr('name');
return !$('form input[type=checkbox][name=' + name +']')
.prop('checked');
} else {
// include all other input
return true;
}
})
.serializeObject();
See the working jsFiddle here: http://jsfiddle.net/nrabinowitz/nzmg7/4/
serializeObject uses serializeArray internally and serializeArray serializes only those elements that would be submitted actually. So using the following code, I have disabled the hidden fields corresponding to checkbox and added a change event to toggle the disbaled state on each hidden input. Since the inputs are disabled, they don't get serialized.
The .serializeArray() method uses the standard W3C rules for
successful controls to determine which elements it should include; in
particular the element cannot be disabled and must contain a name
attribute. No submit button value is serialized since the form was not
submitted using a button. Data from file select elements is not
serialized.
$('form.form-class :checkbox').change(function () {
enableDisableCorrespondingHiddenField($(this));
});
$('form.form-class :checkbox').each(function () {
enableDisableCorrespondingHiddenField($(this));
});
enableDisableCorrespondingHiddenField(checkbox) {
$(":hidden[name='" + checkbox.attr("name") + "']", checkbox.parent()).attr("disabled", checkbox.attr("checked"));
}
Related
On the application I am working on I need to disable an element under one of two different circumstances, one if the logged in user only has read only access to the form, two if the conditional logic set up on the field is met. These forms are being generated dynamically, built on the admin panel with drag and drop fields.
The issue I am having is when the conditional logic case has been met but the form is not read only. In the case I am trying now it's to disable some of the fields if the form is being reopened (already saved).
The input looks like this:
<input name="userName" id="userName" maxlength="64" type="text" class="k-textbox custom-disable" data-bind="value: formData.userName, disabled: isFormDisabled">
The conditional logic sets the disabled property on the input, as well as adding the custom-disable class for CSS. isFormDisabled is a boolean property of the viewModel.
What I would like to do is create a function like this:
ViewModel = kendo.observable({
...,
isFormDisabled: false,
isElementDisabled: function (e) {
var customDisabled = $(e.target).hasClass( "custom-disable" );
return this.get("isEventDisabled")||customDisabled;
},
...
});
and change the binding of disabled to this new function, but since the disabled is not an event, when I log e it's undefined - how can I find the element being bound to this iteration of the callback?
Kendo Dojo
Currently Kendo has its own way for to enable/disable elements, for example, this explains how to enable/disable a Kendo Combobox
This is what I ended up figuring out - for the function:
isElementDisabled: function (eID) {
var me = this;
var element = $("#" + eID);
var customDisabled = $(element).hasClass("custom-disable");
return me.get("isEventDisabled") || customDisabled;
},
and the binding -
<input name="#: columnName #" id="#: columnName #"
data-bind='value: #: dataContainer #.#: columnName #, disabled: isElementDisabled("#: columnName #")'
/>
Since the ID of the element matches the column name and is unique, I can find it by passing that ID into the bound function as a property.
Currently when creating a FormData object, a checked checkbox is added with a value of "on", and an unchecked checkbox is not passed at all.
Do I have to hack in some hidden inputs to properly set checkboxes, or is there some customization I can do with FormData, or pre processing?
I would prefer a checked checkbox to be 1 and an unchecked to be 0. I can already do this myself (ie ugly hack), but I don't see any native way with FormData.
form.addEventListener("submit", function(e) {
e.preventDefault();
const data = new FormData(form);
for (const [name,value] of data) {
console.log(name, ":", value)
}
})
<form id="form">
<input name="normal" type="text" value='example' />
<input id="inpt" name="on" type="checkbox" />
<label for="inpt">on</label>
<br /><button type="submit">submit</button>
</form>
Currently when creating a FormData object, a checked checkbox is added with a value of "on", and an unchecked checkbox is not passed at all.
on is only used if the checkbox is missing a value attribute
Do I have to hack in some hidden inputs to properly set checkboxes
No. That is properly handling checkboxes. It is how they have worked in forms since the form element was added to HTML.
Test for the presence or absence of the checkbox in the code that handles it.
Try this:
var checkbox = $("#myForm").find("input[type=checkbox]");
$.each(checkbox, function(key, val) {
formData.append($(val).attr('name'), this.is(':checked'))
});
It always adds the field to FormData with either a value of true when checked, or false when unchecked.
I took a slightly different approach from the existing answers. I created my form data variable the standard jQuery way inside my form submit event handler:
var form = $(this).get(0);
var formData = new FormData(form);
Based on Quentin's answer, saying that it is only set to 'on' when the value attribute is not available, I just added a document event on change to all checkboxes to set the value when the user checks or unchecks the input.
$(document).on("change", "input[type='checkbox']", function () {
var value = $(this).prop('checked');
$(this).val(value);
});
When my form data object is created in the above way, all checked checkboxes now have the value of 'true' rather than 'on'.
This worked quite nicely for my purposes and seems to me to be a pretty simple fix. Interestingly, having value='false' doesn't do anything as the input is just ignored and not added to the form data object if it is not checked. But obviously that still works.
I am new to js and jquery. Currently, I have a form at form.php which contains a checkbox. When the user clicks submit, the form variables are sent to a form.js file where each value is checked to be null or not.
The form.js file works perfectly, however, for the checkbox nothing seems to happen. I have a feeling this is due to the way I have declared the variable.
The following is the code for the js file:
var email = $('#email').val();
var website = $('#website').val();
var CHECKBOX = $('CHECKBOX').val();
...
...
if (CHECKBOX.checked == FALSE){
var error = true;
$('#notchecked_error').fadeIn(500);
}else{
$('#notchecked_error').fadeOut(500);
}
Try using:
if ( $('#CHECKBOX').prop("checked") )
or:
if ( $('#CHECKBOX').is(":checked") )
Also, be sure your selector for the checkbox is correct.
I see two problems in your code. The first one is that the selector in your CHECKBOX assignation is faulty. It should be
var CHECKBOX = $('#CHECKBOX').val();
or
var CHECKBOX = $('input[type=checkbox]').val();
the second problem is that you are reading CHECKBOX.checked from the val() function, you need to read it from the checkbox itself.
if(CHECKBOX.checked)
$('input[type=checkbox]:checked') // If you have multiple checkboxes you can use this and loop through them to get additional info
$('#checkboxID:checked').length // To get one specific checkbox
`$('CHECKBOX').val();`
Will try to find an element with a tagname of CHECKBOX and return it's value. Presumably you want to reference the checkbox with an ID of CHECKBOX:
var CHECKBOX = $('#CHECKBOX');
To see if it's checked:
if (!CHECKBOX[0].checked) {
// CHECKBOX is not checked
}
You really should learn basic javascript before using jQuery. Usually validation is initiated from a form submit, which can give you are reference to the form. You can then reference all of the form elements as properties of the form, you don't need to create all of those jQuery objects. e.g. if you form is something like:
<form ... onsubmit="validate(this)"... >
<input type="checkbox" name="checkbox">
</form>
Then in your validate function:
function validate(form) {
if (!form.checkbox.checked) {
// the checkbox isn't checked
}
}
You can attach the listener dynamically if you wish.
I am trying to pass a value for when a checkbox is either in a checked state or if it's not checked.
However, it doesn't appear to pass the non-checked state. the code I am using is below:
if (document.getElementById('PRODUCT_REVIEW_EMAILS_FIELD').checked == true){
document.getElementById('PRODUCT_REVIEW_EMAILS_FIELD').value = 'on';
}
else {
document.getElementById('PRODUCT_REVIEW_EMAILS_FIELD').value = 'off';
}
I have added an alert:
alert(document.getElementById('PRODUCT_REVIEW_EMAILS_FIELD').value);
which surprisingly shows the 'off' value - however - this isn't passed successfully.
What am I missing?
This is normal, expected and well-defined behaviour.
Checkboxes have an arbitrary value;
When a checkbox's checked attribute is on, it is submitted as part of a form with that value;
When a checkbox's checked attribute is off, it is not submitted at all.
HTML 4.01 says:
Checkboxes (and radio buttons) are on/off switches that may be toggled by the user. A switch is "on" when the control element's checked attribute is set. When a form is submitted, only "on" checkbox controls can become successful.
And:
When the user submits a form (e.g., by activating a submit button), the user agent processes it as follows.
Step one: Identify the successful controls
Step two: Build a form data set
A form data set is a sequence of control-name/current-value pairs constructed from successful controls. [..]
HTML5 says similar things.
You could write your back-end code to expect fields with a certain name, and react accordingly when they are missing.
You can handle the true on/off values of a checkbox this way (will post when checkbox is on and off). Basically this uses a hidden form field with the name PRODUCT_REVIEW_EMAILS_FIELD and populates it with the value. Hidden form fields always post.
<form>
<input id="tempCheckbox" type="checkbox" name="Temp_PRODUCT_REVIEW_EMAILS_FIELD">
<input id="checkboxvalue" type="hidden" name="PRODUCT_REVIEW_EMAILS_FIELD" value="Off">
</form>
<script type="text/javascript">
document.getElementById("tempCheckbox").onclick = function () {
if (this.checked) {
document.getElementById("checkboxvalue").value = "On";
}
else {
document.getElementById("checkboxvalue").value = "Off";
}
}
// used to run on page load to verify the correct value is set incase your server side
// script defaults the checkbox to on
document.getElementById("tempCheckbox").onclick();
</script>
You can do it on the server side so not to relay on JavaScript.
To do it you must add a reference input field right before every checkbox.
<form>
<input type="hidden" name="checkboxes" value="reference"/>
<input type="checkbox" name="checkboxes" value="checked"/>
</form>
This will make parameters come in array of values: "reference-checked" sequence if checkbox is checked and just "reference" if it is unchecked. You can have arbitrary amount of such checkboxes, this will not affect your logic.
Now for the server side. Assuming that you get your 'checkboxes' as a String array, here's the logic (in Java) to parse the values:
List<Boolean> parsed = new ArrayList<Boolean>();
for (int i = 0; i < checkboxes.length; i++) {
if (i < checkboxes.length - 1 && "checked".equals(checkboxes[i + 1])) {
parsed.add(true);
i++;
else {
parsed.add(false);
}
}
Now you have a nice array of booleans that correlates to the order, amount and state of checkboxes you have.
Is there a way to can access and manipulate the POST params after a form submit has been made. To be more specific, in my submit event handler, how can I do something like
$("#form").submit()
{
//access the request params and manipulate them here
return true;
}
instead of the following hack which I find to be not that elegant.
$("#submit_button").click()
{
// Construct the Request 'params' manually
$.post("/foo/action", params, redirectIfSuccess);
}
You can do it before form submit. Just check the variables in the form on submit event change one or more of them and submit with new data.
$("#form").submit(function() {
$("#form #myInputField").val("Some text here");
return true;
});
With ("#myInputField") you select the input field or you can use ("input[name='myInputField']") to select a input on its name attribute.
After that you can use val() to get or val("Some text") to set the value of the appropriate input. That's all.
To add new input or DOM element you have to use .append(),
Ex:
$("#form").append("<input type="hidden" name="myNewInput" value="1" />");
Have a look here: http://api.jquery.com/append/