I am currently using the validate plugin to validate a form (using ASP.Net controls). I have stripped out the rules from the standard setup within the form.validate method ie:
$("form").validate({
rules: {
ctl00$ContentPlaceHolder1$dgQuestions$ctl14$iRadList_Col0: "required"
}
});
I now have these in various functions which add the ruless depending on what button is clicked. This works fine for text boxes, but for a RadiobuttonList when the plugin tries to add the rule there is an error saying the element is undefined.
function addRuleSet() {
$("#ctl00$ContentPlaceHolder1$dgQuestions$ctl14$iRadList_Col0").rules("add", { required: true });
}
I think the problem is that I am using the name attribute (asp puts $ in )to define the group that the radio buttons belong to rather than an id (, but in the static settings all the elements are definied using the name attribute. Anyway I am not sure how to get around adding a rule for a group of associated radio buttons, any advice would be appreciated.
PS I really need to call the RadioButtonList rather than the individual radio buttons.
You can also apply a rule by setting classes on the element. For example, if you give the class "required" to an input, then the required rule applies to that element. To do this, you'd use the CssClass property on the control. You may need to experiment with compound controls, like RadioButtonList, to make sure that the class is being applied to the input elements generated, not the container. If you have trouble with this, one way to do it would be to add the class using jQuery after the page loads based on a selector.
<asp:RadioButtonList id="RadList" runat="server" CssClass="required">
...
</asp:RadioButtonList>
or
<script type="text/javascript">
$(function() {
$(':radio').addClass('required');
$('form').validate();
});
</script>
For a complex, class-based rule you can add new rules using addClassRules.
<script type="text/javascript">
$(function() {
$.validator.addClassRules({
range0to10: {
range: [0, 10]
},
name: {
minlength: 2,
required: true
}
});
$('form').validate();
});
</script>
<form ... >
<input type="text" name="rating" id="rating" class="range0to10" />
<input type="text" name="firstName" id="firstName" class="name" />
<input type="text" name="lastName" id="lastName" class="name" />
</form>
After days of this driving me mad, asking the question got me thinking how to get the element returning properly, and I came across this method of referencing staright away which allows me to do it:
$("input:radio[name='ctl00$ContentPlaceHolder1$dgQuestions$ctl14$iRadList_Col0']").rules("add", { required: true });
Related
ref: this jsfiddle
The html is:
<script id='radio' type='text/ractive'>
<div>
<input type='radio' name='{{status}}' value='true' />
<input type='radio' name='{{status}}' value='false' />
{{status}}
</div>
</script>
<div id='container' />
and the javascript is:
Item = Ractive.extend({
template : '#radio'
})
new Ractive({
el : '#container',
template : "{{#items:i}}<item status='{{status}}' />{{/items}}",
components : { item : Item },
data:{items :[{status : 'false'},{status : 'true'}]}
})
So there are two items each with a pair of radio buttons to set status to true or false.
Problem is that the 'name' attribute is the same for both items (i.e. in all four radio buttons). So the radio buttons don't behave as two pairs (one per item) but they behave instead as a group of four.
How can this be written such that each item has its own pair of true/false radio buttons?
I found the answer in the Ractive github issues.
As noted in the issue comment, scoping can be achieved by wrapping the radio buttons inside a element. This will not work when adding the form element creates nested forms, but it will work in my case.
I am building a user interface where visitors to a web site are asked questions and must choose answers. The answers are sometimes complex enough that we have decided to use sets of radio buttons, with nested check boxes: each set of check boxes controlled by its radio button. (Much effort has gone into reducing the complexity, etc. and we've also considered other options like drop-downs with long, wordy answers. That's not what this question is about.)
With some JavaScript, we can fairly easily ensure that the relationship between the controls is visually clear. (Note that the following screen captures are mock-ups, and the graphical design is yet to come. The question and answers are also fictional.)
We need to ensure that we also offer the correct experience to people who are using assistive technologies such as a screen reader. I have looked at the various WAI-ARIA attributes which can be used to enhance HTML to allow this. Below is the HTML I used to generate the screen captures.
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<style>
fieldset {width: 300px;}
.pseudoDisabled {
background-color: #f4f2f2;
}
</style>
<script>
$(function(){
$("fieldset.question").each(function(){
// if a radio is followed by a fieldset with the right owning-radio, the
// fieldset should join in with the radio-button logic
$(this).children("input").change(function(){
if (this.checked){
if($(this).nextAll("fieldset:first").attr("data-owning-radio") === this.id){
$(this).siblings("fieldset").prop("readonly", false).removeClass("pseudoDisabled");
} else {
$(this).siblings("fieldset").prop("readonly", true).addClass("pseudoDisabled");
}
}
});
});
// Ensure that clicking on a nested checkbox activates the matching radio
$("[data-owning-radio]").each(function(){
var jThis = $(this);
var owningRadio = jThis.attr("data-owning-radio");
jThis.children("input").change(function(){
$("#" + owningRadio).prop( "readonly", false ).removeClass("pseudoDisabled").prop("checked", true);
});
jThis.click(function(){
$(this).prop("readonly", false).removeClass("pseudoDisabled");
});
});
// We'd have liked to use 'disabled', but then you don't get click events, so
// instead we use readonly for the controls that we don't want to be successful
// and switch to disabled as we submit.
$("form").submit(function(e) {
$("fieldset", this).filter(function(){
return $(this).prop("readonly") == true
}).prop("disabled", true);
});
});
</script>
</head>
<body>
<form>
<div>
<fieldset name="question1" class="question">
<legend>Do you pay tax?</legend>
<input type="radio" name="oq1" id="oq1a1" value="no" />
<label for="oq1a1">No</label><br />
<input type="radio" name="oq1" id="oq1a2" value="yes" aria-controls="q1a2checkboxes"/>
<label for="oq1a2">Yes</label><br />
<fieldset id="q1a2checkboxes" name="q1a2checkboxes" data-owning-radio="oq1a2">
<input type="checkbox" name="questiona2" id="oq2a2a" value="incomeTax" />
<label for="oq2a2a">I pay income tax</label><Br />
<input type="checkbox" name="questiona2" id="oq2a2b" value="vat" />
<label for="oq2a2b">I pay Value Added tax</label><Br />
<input type="checkbox" name="questiona2" id="oq2a2c" value="local" />
<label for="oq2a2c">I pay local tax</label>
</fieldset>
</fieldset>
</div>
<input type=submit>
</form>
</body>
</html>
As you can see, I have used the aria-controls attribute to indicate the relationship between the radio and the fieldset it controls. Is this the correct approach? Is it sufficient, or do I need also to use various other attributes to describe more detailed relationships?
So far my web searches have yielded mostly very abstract standards documents, and not much in the way of clear advice, so any good references would also be very welcome.
Another jQuery noob question - what am I doing wrong??
I have some HTML markup rendered by ASP.NET 3.5 webforms which looks like this:
<input id="ctl01_cphContent_pnlBasicInfo_chkRC"
type="checkbox" name="ctl01$cphContent$pnlBasicInfo$chkRC" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_chkRC">Recurrent Charges</label>
<span id="ctl01_cphContent_cntPromos_pnlBasicInfo_lblPromoValidFor"
class="rcPromo">Validity:</span>
<span class="rcPromo">
<input id="ctl01_cphContent_pnlBasicInfo_rbnDiscountValidFor"
type="radio" name="ctl01$cphContent$pnlBasicInfo$discountValidFor"
value="rbnDiscountValidFor" checked="checked" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_rbnDiscountValidFor">valid for</label>
</span>
<span class="rcPromo">
<input id="ctl01_cphContent_pnlBasicInfo_rbnDiscountValidUntil"
type="radio" name="ctl01$cphContent$pnlBasicInfo$discountValidFor"
value="rbnDiscountValidUntil" />
<label for="ctl01_cphContent_cntPromos_pnlBasicInfo_rbnDiscountValidUntil">valid until</label>
</span>
<input name="ctl01$cphContent$pnlBasicInfo$txtDiscountMonths" type="text"
id="ctl01_cphContent_pnlBasicInfo_txtDiscountMonths"
class="textbox" class="rcPromo" originalValue="" style="width:30px;" />
<span id="ctl01_cphContent_cntPromos_pnlBasicInfo_lblMonths" class="rcPromo"></span>
<input name="ctl01$cphContent$pnlBasicInfo$txtDiscountUntil" type="text"
id="ctl01_cphContent_pnlBasicInfo_txtDiscountUntil"
class="textbox" class="rcPromo" originalValue="" style="width:150px;" />
I have a checked "chkRC" which I want to trap and use to enable/disable other UI controls
I have a number of labels, input (type=radio) and input (type=text) UI controls. These are all marked with the "rcPromo" dummy CSS class
I have a CSS class called "textbox" for the normal textbox and "textboxDisabled" for the disabled state of the textbox, in an externally referenced CSS file, that work OK (when used in server-side code, that is)
What I'm trying to accomplish in jQuery is this: when the "chkRC" checkbox is disabled, I want to disable all relevant UI controls.
My jQuery looks like this:
$(document).ready(function() {
$("#<%= chkRC.ClientID %>").click(function() {
$('.rcPromo > :label').toggleClass('dimmed');
if (this.checked) {
$('.rcPromo').removeAttr('disabled');
$('.rcPromo .textboxDisabled').addClass('textbox').removeClass('textboxDisabled');
}
else {
$('.rcPromo > :input').removeAttr('checked');
$('.rcPromo .textbox').addClass('textboxDisabled').removeClass('textbox');
$('.rcPromo').attr('disabled', true);
}
});
});
It works fine for the labels and the radiobuttons - but I just can't get it to work with the textboxes - they just stay the same all around, nothing changes (they don't get disabled and they don't change their appearance to indicate that they're disabled, either).
I don't understand this - I do see several (a few more than in the sample) textboxes, which are <input type="text"> in HTML, and they do have the class="rcPromo" and class="textbox" on them - so why doesn't jQuery find and update those?
Any ideas?
Marc
I can't think of a way to augment the css class names that are assigned to controls from the skin file (phoenix is correct, the class names need to be added in the same attribute).
I can think of a few workarounds though:
--> You can wrap all the textboxes you want disabled in a div with a given class:
<div class="disable_textbox"><asp:textbox id="".../></div>
and then disable them by selecting:
$('.disable_textbox input').attr('disabled', true);
--> You can include character strings in the ID of the textboxes you want disabled:
<asp:textbox id="txtDiscountUntil_DisableMe" ... />
and then disable them like so:
$("input[id*='DisableMe']").attr('disabled', true);
--> You can add a custom attribute to your textbox:
txtDiscountUntil.Attributes.Add("disableme", "true");
and then disable them like so:
$("input[disableme='true']").attr('disabled', true);
Your HTML markup is not the correct one.
You can't add two classes like the one in your code.
Two classes can be added like this
<input type="text" class="Class1 Class2" />
and not like
<input type="text" class="Class1" class="Class2" />
Why don't you use hasClass to check whether the element has this class set or not?
I think you have to give this in an OR condition for the two classes.
I am writing a form using jQuery and encounter some difficulties.
My form works fine in static page (html).
However, when I use the form in dynamic page(aspx), the form does not behave correctly.
I cannot append items to the form and call the form.serialize function.
I think the error occurs when a form is inside another form (.aspx code needs to enclosed by a form tag).
What should I do?
Let me give a simplified version of my code:
<form name="Form1" method="post" id="Form1">
some content
<form name="form_inside">
<input name="fname" type="text" />
</form>
</form>
jQuery code:
$("#form_inside").append($("<input type='text' name='lname'>"));
When the user submits,
$("#form_inside").serialize();
// it should return fname=inputfname&lname=inputlname
I want to append element to "form_inside" and serialize the form "form_inside".
The form "Form1" is required by the aspx and I cannot remove it.
Could you just serialize the fields inside Form1?
I don't know anything about ASP, but it seems that you're not doing a straightforward "submit" anyway - so does it really matter if the fields aren't within their own separate form?
You could possibly group the fields you're interested in within a <div> or something, e.g.:
<div id="my-interesting-fields">
...
</div>
then substitute #form-inside with #my-interesting-fields where appropriate - is that helpful at all?
Edit
OK, a quick glance at the jQuery code suggests that serialize() depends on the form's elements member.
I suppose you could hack this in a couple of different ways:
Copy all elements from #my-interesting-fields into a temporary <form> that you dynamically create outside Form1, then call serialize() on that. Something like:
$("#Form1").after("<form id='tmp-form'></form>").
append("#my-interesting-fields input");
$("tmp-form").serialize();
Or, create an elements member on #my-interesting-fields, e.g.
$("#my-interesting-fields").elements = $("#my-interesting-fields input");
$("#my-interesting-fields").serialize();
I haven't tried either of these, but that might give you a couple of ideas. Not that I would necessarily recommend either of them :)
Because you can't have nested <form> tags you'll need to close off the standard dotnet form tag like below:
<script type="text/javascript">
$(document).ready(function() {
$("#form_inside").append($("<input type='text' name='lname'>"));
$("#submitBtn").click(function() {function() {
var obj = $("#form_inside *");
var values = new Array();
obj.each(function(i,obj1) {
if (obj1.name && !obj1.disabled && obj1.value) {
values.push(obj1);
};
});
alert(jQuery.param(values));
}); });
});
</script>
<form id="form1" runat="server">
<div>
<div id="form_inside" name="form_inside"> <input name="fname" type="text" /><input type="button" id="submitBtn" /></div>
</div>
</form>
jQuery.param on a array of form elements will give you the same results as .serialize()
so you get all elements in div $("#form_inside *) then filter for elements then on the result jQuery.param will give you exactly what you need
I would really like use the jQuery Validation plugin in my ASP.NET Web Forms application (not MVC). I find it easier than adding asp validators everywhere and setting the control to validate field on all of them.
I am just having some issues both when setting the class like this class="required email" which I think has something to do with having a form tag within the main form tag.
I also run into issues when calling the jquery validate using the names which become mangled in an asp control
// validate signup form on keyup and submit
$("#signupForm").validate({
rules: {
username: {
required: true,
minlength: 2
}, },
messages: {
username: {
required: "Please enter a username",
minlength: "username at least 2 characters"
},
}.
.......
<p>
<label for="username">
Username</label>
<input id="username" name="username" />
</p>
because this
<asp:TextBox ID="tbUsername" runat="server"></asp:TextBox>
renders as
<input name="ctl00$ContentPlaceHolder1$tbUsername" type="text" id="ctl00_ContentPlaceHolder1_tbUsername" />
and mangles the name. I can get the ClientID using <%=tbUsername.ClientID %>but that doesn't work with ClientName
Has anyone had any success using the jquery validator plugin with asp.net?
If so what about using multiple forms much like using separate validation groups?
You can checkout the rules add function, but basically here's what you can do:
jQuery(function() {
// You can specify some validation options here but not rules and messages
jQuery('form').validate();
// Add a custom class to your name mangled input and add rules like this
jQuery('.username').rules('add', {
required: true,
messages: {
required: 'Some custom message for the username required field'
}
});
});
<input name="ctl00$ContentPlaceHolder1$tbUsername" type="text" id="ctl00_ContentPlaceHolder1_tbUsername" class="username" />
This way no need to worry about the crappy identifiers generated by the webforms engine.
Here are examples of using the jQuery Validation plugin with WebForms and emulating the concept of validation groups with it. It actually works pretty well once you smooth out a couple issues.
$("#signupForm").validate({
rules: {
<%= tbUsername.UniqueID %>: {
required: true,
minlength: 2
}, },
messages: {
<%= tbUsername.UniqueID %>: {
required: "Please enter a username",
minlength: "username at least 2 characters"
},
});
<asp:TextBox ID="tbUsername" runat="server"></asp:TextBox>
You can check xVal.webForms here: http://xvalwebforms.codeplex.com/
Tested what Darin Dimitrov said and it works perfectly, but if you don't want to set a specific class to each of your fields, you can use jQuery selectors:
$('form').validate();
$('input[id$=Username]').rules('add', {
required: true,
messages: {
required: 'Some custom message for the username required field'
}
});
<input name="ctl00$ContentPlaceHolder1$tbUsername" type="text" id="ctl00_ContentPlaceHolder1_tbUsername" />
The best solution is use "<%=tbUsername.UniqueID %>" instead of tbUsername in jQuery rules.
$("#signupForm").validate({
rules: {
"<%=tbUsername.UniqueID %>": {
required: true,
minlength: 2
}, },
messages: {
"<%=tbUsername.UniqueID %>": {
required: "Please enter a username",
minlength: "username at least 2 characters"
},
}.
I recently posted a patch file for xVal.WebForms which resolves the multiple forms issue relaying on the well known ASP.Net validation Group. This patch also supports the ASP.Net CausesValidation property.
Yo can read about it here: http://cmendible.blogspot.com/
A great way to do this is to use:
<%= textbox.Name %> or <%= textbox.ClientId %> whenever you need to reference a server item.
i.e.
var phoneNumb = $('#<%= tPhone.ClientID %>').val();
or
$("#signupForm").validate({
rules: {
<%= username.Name %>: {
required: true,
minlength: 2
}, },
messages: {
<%= username.Name %>: {
required: "Please enter a username",
minlength: "username at least 2 characters"
},
}.
.......
For SharePoint 2010 I found with loading different usercontrols as views (via ajax) that this worked if you move javascript into a library and can't use server tags for the control id's like this:
e.g #<%= tPhone.ClientID %>
$('input[id$=tPhone]').rules('add',
{
required: true,
messages:
{
required: 'Some custom message for the username required field'
}
});
Further to this if you dynamically load a user control via Ajax then you cannot use $(document).ready
You will have to encapsulate the jQuery in a function library if its on the User Control at (server side event) page load its fine but in the scenario its loaded via Ajax with the Update Panel it will not dance.
I have not tried loading usercontrols via jQuery yet, this looks heavy and appears to load the whole page albeit perhaps slightly quicker or not.
Tests comparing loading techniques showed the Update Panel was as fast and resulted in the same or smaller page sizes than other techniques and basically loaded quicker or much more data as quick or quicker.
I recommend using jQuery.simple.validator, its easy, lightweigh and customizable validator compatible with asp.net web forms, because basically it can perform validations in any container, not only
https://github.com/v2msoft/jquery.simple.validator
I recommend you check the plugin and the documentation.
Usage:
<script type="text/javascript" src="/Content/js/jquery-plugins/jquery.simple.validator.js"></script>
<div id="container">
<!-- REQUIRED FIELD -->
<label>Required Field: </label><br/>
<input type="text" id="required_field_control" data-required data-required-msg="Field is required" /><br /><br/>
<input type="button" value="Validate" onclick='javascript:validate();' />
</div>
<script type="text/javascript">
function validate() {
$("#container").initialize();
var ok = $("#container").validate();
if (!ok) alert("There are errors");
else alert("Form is ok");
}
</script
The information in this article led me to use Control.ClientID when looking for a match with jQuery... Very useful information...
<label for="<%= tbName.ClientID %>">Name</label>
<input id="cphBody_tbName" runat="server" .../>