a developer's notes – a semi-technical web development BLOG

November 13, 2014

Form Validation with Javascript events. Handle Input, Paste, and Keyup across all browsers

Filed under: Javascript / JQuery — Duy Nguyen @ 12:47 pm
Tags: , , , , , , , ,

While testing mobilePay in Chrome on an Android device, it was discovered that the
keyupevent was not firing for validation. Our response was to include input, an HTML5 event, to ensure that changes were firing the validation handlers.

$('form :input').on('keyup input', this.toggleSubmitBtn);

Currently, we are validating the form on every user’s input change, which would enable/ disable the submit button. The disadvantage of this is that we have to capture every single event that the user could possibly interact with the element.

The paste event is one of the events that we recently have implemented to handle. The inputevent we realize fires when the user pastes in an HTML5 browser, which means only non-HTML5 browsers actually need the pasteevent. Below is a table of support for paste validation:

$('form :input').on('keyup input paste', this.toggleSubmitBtn);

The paste event fires across all test devices, but javascript validation logic is carried out beforethe data on the clipboard gets placed into the element. Because all the browsers except for IE8 supported HTML5, however, the inputevent fired afterthe clipboard data was placed in the element. Without the inputevent, none of the browsers supported paste validation.

Solution

InputPropertyChange: function () {
    if (!window.addEventListener) { //IE 5-8 
        var $inputs = $("input[type!='hidden']");
        $.each($inputs, function (index, input) {
            $(index).on('paste'), function () {
                setTimeout( function() {
                    $(input).trigger('keyup');
                }, 250);
            }                
        });
    }
}

This was written up by my colleague Will Hanson and I.

Advertisements

April 25, 2014

jquery.validate : Unable to get property ‘getAttribute’ of undefined or null reference

Filed under: Javascript / JQuery — Duy Nguyen @ 12:31 pm
Tags: , , , , ,

I got this error recently in jquery.validate.js:
“Unable to get property ‘getAttribute’ of undefined or null reference”

Jq_ErrorAttr

GetAttributeError

Turns out the error was from a input type checkbox needing a name attribute and not just an Id attribute.

March 21, 2014

Using jquery.validate.unobtrusive with jquery.maskedinput

Use a regular expression validator with your view model property. This regex will match “(999) 999-9999” and anything after. The input will be restricted with jquery.maskedinput to only accept valid numbers. Whether the user enters an extension or not, the regex will still get validated. We only need to valid the minimum required phone number.

Using the Data Annotation on your view model will allow the client side unobtrusive validation to work when the user enters in a phone number with the optional extension.

View Model property

[Required]
[DataType(DataType.PhoneNumber)]
[RegularExpression(@"^([(][0-9]{3}[)][ ][0-9]{3}[-][0-9]{4})(.*)$", ErrorMessage = "Phone number busted.")]
[DisplayName("Contact Phone Number")]
public string ContactPhoneNumber { get; set; }

In your view

<div>
	@Html.EditorFor(x => x.ContactPhoneNumber)
	@Html.ValidationMessageFor(x => x.ContactPhoneNumber)
</div>

Script:

if ($("input[type=tel").length > 0) {
	$("input[type=tel").mask("(999) 999-9999? ext.9999", { placeholder: " " });

	// @Html.EditorFor is used to render any inputs that need the html 5 type attributes.
	// But @Html.EditorFor, won't allow you to add a css class, so we do it here.
	$('input[type=text],input[type=tel],input[type=datetime],input[type=date],input[type=number],input[type=password],textarea,input[type=email],input[type=url],input[type=zip]').each(function (idx, item) {
		if (!$(item).hasClass('form-control')) //class only for Bootstrap styling
			$(item).addClass('form-control');
	});

}

March 8, 2014

Jquery Validation Unobtrusive with ASP.NET MVC

Filed under: Javascript / JQuery — Duy Nguyen @ 2:46 pm
Tags: , , , , ,

Things to remember:

1. Input controls must be wrapped within a form
2. For validation messages to appear, you must have a validation message property for each input.

@Html.TextBoxFor(x => x.MyTextBox)
@Html.ValidationMessageFor(x => x.YourProperty)

3. If you want the validation message to appear immediately upon page load, you have to run this jquery method:

$('form').valid();

4. You can customize your validation message style with these css classes that you can override:

.field-validation-error span{
     color: red;
}

//Adds an asterisk before the message
.field-validation-error span:before{
     content: "*";
}

input.input-validation-error{
     border: 1px solid red;
}

January 29, 2014

Dynamically added checkbox not posting value to Action Method in controller

I noticed that @Html.CheckboxFor(model => model.MyCheckBox) creates a hidden input with the same name as the actual checkbox. So when you dynamically add a checkbox, make sure you also add in a hidden input with the same name attribute.


var chkboxDiv = $(document.createElement('div')).attr({
	id: 'dynamicChkBoxdiv_'
});

chkboxDiv.html(
	'<input ' +
		'class="myChkBx"' +
		'type="checkbox"' +
		'value=""' +
		'data-val-required="The Active field is required."' +
		'data-val="true"' +
		'name="myChkBxName"/>' +
	'<input ' +
		'type="hidden"' +
		'value=""' +
		'name="myChkBxName"/>' +
);

You also need to add a click event handler to update the hidden value so when the form is submitted, the controller will get the correct ‘checked’ value.

Notice the second parameter that specifies a css class. When you add your dynamic controls, add a css class so you can specify which elements should get the click event delegate. All of your dynamically added controls that have the css class, will now have the same click event.

$("#dynamicChkBoxdiv_").parent().on("click", '.myChkBx', function (e) {
	var name = e.target.name;
	var checkVal = e.target.checked;
	$("input[name^='" + name + "']").val(checkVal); //this will update both the checkbox and hidden input's value
});

Binding Click Events to dynamically added controls with jQuery

Filed under: Javascript / JQuery — Duy Nguyen @ 1:23 pm
Tags: , , , , , , , , , ,

When you dynamically add controls, make sure the container that the controls are added to, has an ID attribute.

Example:

<div id="dynamicCollectionDiv">
           //dynamic controls are added inside this div
</div>

Then you can use jquery to add a ‘click’ delegate on any newly added controls. You used to be able to use the “.live” method but this is now deprecated. Use the “.on” method instead. You must reference the parent container to do the actual binding.

$("#dynamicCollectionDiv").parent().on("click", '.dynamicControlCssClass', function () {
        // do something
    });

Notice the second parameter that specifies a css class called “dynamicControlCssClass.” When you add your dynamic controls, add a css class so you can specify which elements should get the click event delegate. All of your dynamically added controls that have the css class “dynamicControlCssClass,” will now have the same click event.

January 22, 2014

MVC 4 – Using HTML5 “data-” attributes with Jquery

Filed under: ASP.NET MVC,Javascript / JQuery — Duy Nguyen @ 11:55 am
Tags: , , , , ,

You can create data- HTML attributes with your controls using this technique.

Define a new HTML Attributes anonymous object with your Html helpers. Below, I create a text box with some additional properties I want to be able to access with jQuery. Using properties that start with “data_”, you will be able to access the property with jquery’s data() method. Note: using property names that start with “data-” will result in a compilation error.

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>
<h1>Tesing data-properties in MVC</h1>

<div>@Html.Label("Product: ")@Html.Label("Book")</div>
@Html.Label("Quantity:")

@Html.TextBox("myTextbox", "", 
    new
    {
        @class = "myCssClass",
        data_my_new_property = "hello world",
        //data-dashTest = "hello dashTest", This will not work. Compilation Error 
        data_product_id = "productId1",
        data_minimum ="0",
        data_price = "5.00",
        data_val = "true",
        data_val_number = "The field Quantity must be a number.",
        data_val_range = "The field Quantity must be between 0 and 10000.",
        data_val_range_max = "10000",
        data_val_range_min = "0",
        data_val_required = "The Quantity field is required.",
        @style = "width: 100px;"
    })

<input type="button" value="clickMe" />

<script>
    $(function () {
        var $qtyInput = $('.myCssClass');
        var myProperty = $qtyInput.data().price; // value is 5.00
        //You can also do this
        var txBox = document.getElementByID('myTextbox');
        console.log(txBox.getAttribute('data-my-new-property'));
    });

</script>

This is the HTML that gets rendered

<input name="myTextbox" 
class="myCssClass" 
id="myTextbox" 
style="width: 100px;" 
type="text" value="" 
data-val-required="The Quantity field is required." 
data-val-range-min="0" 
data-val-range-max="10000" 
data-val-range="The field Quantity must be between 0 and 10000." 
data-val-number="The field Quantity must be a number." 
data-val="true" 
data-my-new-property = "hello world",
data-product-id="productId1" 
data-price="5.00" 
data-minimum="0">

Here is what jquery’s data() method converts property names to. Interestingly, the underscores are removed and camel casing is applied to the name.

data-dash-watch

Here is another good article on the subject.
http://unmatchedstyle.com/news/html5-data-attributes-jquery.php

JQuery doesn’t work with ASP.NET MVC 4 Application. $ is not defined

Filed under: ASP.NET MVC — Duy Nguyen @ 11:29 am
Tags: , , , , , , , ,

Why is JQuery Referenced In the Body Tag with a default ASP.NET MVC 4 Application?

In short, script loading and executing, blocks the rendering of a web page. So it is recommended to move script references in the body tag. So Microsoft decided to move the @Scripts.Render in the body tag as the default location for _Layout.cshtml. If you’re using jquery’s onReady() function in your View, make sure you declare your script tag within a scripts @section like this:

@section Scripts {
    <script type="text/javascript">

    $(function () { //Same as $(document).ready()
        alert("hello");
    });
       
    </script>
}

If you declare a traditional <script> tag outside of “@section Script{}” at either at the beginning or end of your View file, you will get an error, $ is not defined. This is because the _layout view calls @RenderBody() before the jquery script bundle.

But if you still want to declare your <script>tags and not use @section Script{}, for whatever reason, remember to comment out or delete the

@Scripts.Render("~/bundles/jquery")

reference in the body tag in the _Layout.cshtml file and move it to the head tag.

Here is a sample _Layout.cshtml.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery") @*--Need to move this to the <head> section otherwise you will get '$ is undefined.'*@
</head>
<body>
    @RenderBody()

    @*-- Commenting out the default location because we are not using @section Scripts {} section. By default, Microsoft added all script rendering in the <body> tag for better performance. But this will only work if you define your script tags within @section Scripts {}.*@
    @*@Scripts.Render("~/bundles/jquery")*@ 
    @RenderSection("scripts", required: false)
</body>
</html>

January 8, 2014

How to add / remove textbox dynamically with jQuery

Filed under: Javascript / JQuery — Duy Nguyen @ 10:00 pm
Tags: , , , , , , ,

This is a great tutorial!
http://www.mkyong.com/jquery/how-to-add-remove-textbox-dynamically-with-jquery/

<html>
<head>
<title>jQuery add / remove textbox example</title>
 
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
 
<style type="text/css">
	div{
		padding:8px;
	}
</style>
 
</head>
 
<body>
 
<h1>jQuery add / remove textbox example</h1>
 
<script type="text/javascript">
 
$(document).ready(function(){
 
    var counter = 2;
 
    $("#addButton").click(function () {
 
	if(counter>10){
            alert("Only 10 textboxes allow");
            return false;
	}   
 
	var newTextBoxDiv = $(document.createElement('div'))
	     .attr("id", 'TextBoxDiv' + counter);
 
	newTextBoxDiv.after().html('<label>Textbox #'+ counter + ' : </label>' +
	      '<input type="text" name="textbox' + counter + 
	      '" id="textbox' + counter + '" value="" >');
 
	newTextBoxDiv.appendTo("#TextBoxesGroup");
 
 
	counter++;
     });
 
     $("#removeButton").click(function () {
	if(counter==1){
          alert("No more textbox to remove");
          return false;
       }   
 
	counter--;
 
        $("#TextBoxDiv" + counter).remove();
 
     });
 
     $("#getButtonValue").click(function () {
 
	var msg = '';
	for(i=1; i<counter; i++){
   	  msg += "\n Textbox #" + i + " : " + $('#textbox' + i).val();
	}
    	  alert(msg);
     });
  });
</script>
</head><body>
 
<div id='TextBoxesGroup'>
	<div id="TextBoxDiv1">
		<label>Textbox #1 : </label><input type='textbox' id='textbox1' >
	</div>
</div>
<input type='button' value='Add Button' id='addButton'>
<input type='button' value='Remove Button' id='removeButton'>
<input type='button' value='Get TextBox Value' id='getButtonValue'>
 
</body>
</html>

August 29, 2013

Jquery Error: SCRIPT1028: Expected identifier, string or number

Filed under: Javascript / JQuery — Duy Nguyen @ 5:04 pm
Tags: , , , ,

When getting this error in Internet Explorer, check the mode that IE is running. Make sure you are not running in Quirks Mode, or Compatibility Mode, or IE 7/8 Standards.

Also, check under Tools >> Compatibility View Settings >> and uncheck

“Display all websites in Compatibility View”
“Display all intranet sites in Compatibility View”

Next Page »

Blog at WordPress.com.