how does unobstrusive javascript work in ASP.NET MVC3? - asp.net-mvc

Is there a tutorial or explanation how MVC3 implements unobstrusive javascript using HTML5 data tags? I would like to know how I can extend this practice for my own javascript, espescially, how are the data tags efficiently parsed to execute javascript, to attach event handlers, etc.?

In ASP.NET MVC 1 and 2, client side validation and any AJAX behavior meant that ASP.NET MVC would automatically generate javascript for validation or AJAX class. The result was a <script> tag with javascript embedded that would be outputted on the HTML page or data in the event handlers of an input (like onclick).
Unobtrusive javascript eliminates the need to embedded javascript in the HTML page by placing all necessary things in data- attributes on the element. With this in place, jquery.validate.unobtrusive will validate and do AJAX class based on the information in the data- attributes of the input control.
For more details, take a look at this asp.net mvc 3 tutorial which offers a quick example. The unobtrusive explanation is towards the end under the second Enabling Client-Side Validation.
Take a look at this blog post which displays the difference of output for unobtrusive and normal validation.

Basically it's just using jQuery to attach event handlers rather than putting script directly in the html attributes.
For example a document ready event containing
$("#button1").click(DoStuff);
and the html
<button id="button1" />
is equivalent to
<button id="button1" onclick="DoStuff()" />
In this example it's not a huge difference, but for more complex cases it makes the code much cleaner, especially if you want to use anonymous callback functions.

Look in the unobtrusive script files (like jquery.unobtrusive-ajax.js) where you'll find it's just a case of using selectors to find elements with data- attributes.
For example:
$("a[data-ajax=true]").live("click", function (evt) {
evt.preventDefault();
...
});
$("form[data-ajax=true]").live("submit", function (evt) {
...
});
I've started using my own data- attributes to hookup features like autocomplete and datepicker. For example, adding an input with a data-autocomplete attribute pointing to a remote data source, then using jQuery to wire it up unobtrusively.
$(":input[data-autocomplete]").each(function () {
$(this).autocomplete({ source: $(this).attr("data-autocomplete") });
});
Demonstrated here, if you are interested: http://www.pluralsight-training.net/microsoft/players/PSODPlayer.aspx?author=scott-allen&name=mvc3-building-ajax&mode=live&clip=0&course=aspdotnet-mvc3-intro

Related

ASP.NET MVC AJAX actionlink injects onclick attribute

I have a partial view which outputs a list of editors. Each editor in the list has a delete link, which is called using #Ajax.actionlink, like this:
if(Model.Any()){
<ul>
#foreach (var editor in Model)
{
<li>#editor.firstName #editor.lastName, #editor.emailAddress (#Ajax.ActionLink("Delete", "DeleteEditor", "EditorSurface", new { editorId = editor.id }, new AjaxOptions()))</li>
}
</ul>
}
I've included #using System.Web.Optimization; in my view and am calling the jquery unobtrusive ajax script from my view too:
#Scripts.Render("~/scripts/jquery.unobtrusive-ajax.min.js")
The issue is that when I view source, the rendered mark-up for my editor list items is like this:
<li>John Smith, johnsmith#example.com (Delete)</li>
I was a little disappointed to see the inline JavaScript in the delete links and was hoping for something a little 'cleaner' (possibly data attributes or something?). It strikes me this is going to be difficult to hook into (to provide confirmation messages etc).
Question is, is this the expected output of AJAX in ASP.NET MVC? I'm very new to this so not sure if I'm doing something wrong in my implementation.
Many thanks.
Yes, this is the markup the Ajax.* family of helpers produces. My recommendation in general, and especially in light of the fact that you don't want the on* attributes added, is to avoid these helpers like the plague. You'll have much cleaner and maintainable (though slightly more verbose) code handling AJAX yourself, i.e. just add a standard Html.ActionLink and then use jQuery to attach an event handler that calls the AJAX. Plus, when something goes wrong, as it almost inevitably does, you have full knowledge and control over the JavaScript that is running, rather than being at the mercy of some opinionated Microsoft dev.

jquery .html(' <%jsp scriplet%>');

I would like a for loop in jquery using .html()
like this:
.html('<select property="doctype" name="doctype"><%for (String number : list)
{%>'<option value="'<%=number%>'>'<%out.println(number); %>'</option>'<% } %>'</select>');
In Java's for each loop list it uses an object of java.util.ArrayList<String>.
Here the .html(); function will call when we click on add button.
Here my question is it possible to write jsp scriplet code in .html() of jquery.
function will call when we click on add button.
No you can't.
Jsp is compile time.
More over java script plays on client side and jsp playes on server side.
jsp ,jsf and other kinds of java web technologies are rendered on the server side. Since jquery is a client side technology, it's not possible.
Instead, you can make ajax calls via jquery and update the html.
You cannot have the client execute Java in your scriptlet. Fortunately, what you want to do is very common.
Don't try to dynamically generate JavaScript in a scriptlet or jsp. It's very easy to make a mistake and end up with malformed JavaScript.
Instead, use a .jsp to spit out HTML. Then use static JavaScript to grab that HTML and put it where you want in the DOM.
For example, your jsp file could look something like this:
<div id="destination">The select element will be added to this div.</div>
<select id="my-select" property="doctype" name="doctype">
<c:forEach items="${list}" var="number">
<option value="${number}">${number}</option>
</c:forEach>
</select>
<script>
$('#destination').append($('#my-select'));
</script>

How to make form elements read only in GSP?

Hi i have a form in GSP and I want to make all the form elements read only after submit.
Is there any way to do it. I have form elements like textboxes, dropdowns attachment field......
I am using G:Form
I am also using java script in my GSP.
Please help me out
Thanks.
Keep in mind that even if you set the tags as readonly on the server side, users can still change them through a variety of means, and whatever the value on the form is before it gets sent back to you.
You can use an onsubmit event in the form tag, calling a JavaScript function which will disable any form elements you want to affect. Since GSP is server pages, not the browser, it will not normally be able to help you in this respect.
Certainly the easiest way is client-side with jQuery:
$(function() {
$('input, select, textarea').attr('disabled', 'disabled');
});

Helper for PagedList supporting unobtrusive Ajax in ASP.NET MVC

I'm currently using PagedList (https://github.com/TroyGoode/PagedList/) to manage my paging in an ASP.NET MVC application.
As of today I have started converting some parts of the application to use AJAX, which ASP.NET MVC makes quite easy.
The first problem I have run into however is that the PagedList.MVC helper #Html.PagedListPager is not in any way compatable with unobtrusive AJAX.
All I really need to do is add some attributes to the paging links (see below) and the rest would be taken care of automatically. PagedListPager does not provide any way to do this however.
data-ajax="true" data-ajax-mode="replace" data-ajax-update="#SearchResults"
Has anyone run into this and found an elegant solution?
I have added support for unobtrusive AJAX:
https://github.com/TroyGoode/PagedList/issues/26#issuecomment-6471793
I believe this may be the most elegant solution.
#Html.PagedListPager((IPagedList)Model.Articles, page => Url.Action("Index", new { s = Model.SearchString, page = page }))
<script>
var pages = $('#pages a[href^="/"]');
pages.attr('data-ajax', 'true')
.attr('data-ajax-mode', 'replace')
.attr('data-ajax-update', '#SearchResults')
.attr('data-ajax-method', 'post');
</script>
Quick jQuery hack to add the necessary attributes to all links in order for them to be picked up by the unobtrusive ajax module.
The [href^="/"] part ensures that only the clickble links will be modified. If you don't use this, the greyed out Previous link will be clickable.

JQuery UI control defined via HTML attributes instead of JavaScript

This question comes out making use of the HTML helpers in ASP.NET MVC and jQuery. For example, if I define an extension method like the following:
<:% Html.DatePickerFor(x => x.StartDate) %>
I would want it to make use of the jQuery DatePicker. However, this either means I need to manually add to the header the invocation of the DatePicker method (in which case there is no point to the DatePickerFor method), or clutter up the HTML with a whole bunch of script tags that are invoked upon document.ready.
One thought I had was the idea that instead of add the appropriate jQuery UI behavior to a HTML element via Javascript, you could do it via additional attributes, such as the following:
<input id="foo" css="widget-ui-datepicker" widget-alt-field="#fooalt" />
jQuery could then just looks for all elements with the right css class and collect together all the widget-* values and use them to build the "options" that is used to invoke the datepicker method in the first place.
This is the type of idea that could go directly into the widget factory. What are people's thoughts on this?
I typically have this line in my master page:
$(".datepicker").datepicker();
and then just stick the datepicker class on any textbox that I want to use it on.
but it would be a timesaver to have an extension method instead of always writing new { #class: "datepicker" }
I like it.

Resources