Null !== Steve

Steve Gentile's Tech Blog – Thoughts and Musings

Archive for the category “jQuery”

ASP.NET MVC – jQuery – Json.. Cascading Dropdown

I’m less interested in the ‘cascading dropdown’ part of this post , as I am in demonstrating how json and jquery can be your friends in the asp.net mvc world.

Let’s start by a description of the ‘problem’:  On populating a page, we need to query for a set of companies and display those to the user.  Upon selection of a company, we need to populate another dropdown of the banks associated to that company.  You can fill in the blanks for ‘companies’with ‘banks’ – basically a one to many.  In my situation, I use lazy loading and do not need to pull all the banks in when the page loads.

First let’s look at the ‘onLoad’ of the page via jQuery:
$(function () {
  $("#companies").change(function () {
    LoadBanks($("#companies").val());
    });
  });

I’ve simplified this from the code to show the essentials.  I’m handling the onChange of the companies drop down list, something like this:
Select Company: <%= Html.DropDownList("companies", new SelectList(Model, "Companyid", "Name"), string.Empty)%>
The Model is my list of ‘Company’ objects.  The value is the id and the text is the name.
From the above javascript, you’ll see that when the dropdown item is selected I will be passing the selected value – which is the id – to the LoadBanks function:

function LoadBanks(companyId) {
 $.ajax({
  type: "POST",
  url: BuildUrl("Company/LoadBanks"),
  data: ({ id: companyId }),
  dataType: "json",
  beforeSend: function () {
$.blockUI({ message: "Retrieving Banks..." });   //this is great plugin - 'blockUI'
},
success: function (positivePayBanks) {
  $("#positivePayBanks").find('option').remove();
  $banks = $("#positivePayBanks");
  $.each(positivePayBanks, function (i, bank) {
  if (i == 0) { $("#BankID").val(bank.BankID); }
   $banks.append('<option value="' + bank.BankID + '">' + bank.BankName + '</option>');
  });
$.unblockUI();
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
  $.unblockUI();
  var errMsg = "<P>Error Loading: " + XMLHttpRequest.responseText + "<br/>";
  $("#status").html(errMsg).show("slow");
}
});
}

So, what is going on in this call?

type: "POST"
url: BuildUrl("Company/LoadBanks"),   <-- the BuildUrl is just a helper call - basically this is the REST call to the controller/action
data: ({ id: companyId }),   <-- this is the params being sent to the Action.  I'm passing the selected company id
dataType: "json",   <--  I'm saying that the returning data will be json.

Let’s step out of the javascript/html to just show how easy it is to serialize the list of banks to json in mvc:
This isn’t too exciting but here is the controller action for ‘LoadBanks’:

[HttpPost]    <-- I'm requiring this to be a post here
public ActionResult LoadBanks(string id) <--- this id will pick up the id passed in the ajax call above
{
  var positivePayBanks = _companyService.GetBanksByCompanyId(new Guid(id));
  return Json(positivePayBanks);
}

Pretty boring isn’t it?  The simplicity here is appreciate though as mvc includes a JsonResult that will take the list of banks and generate the json!
Here is the select html:

<select id="positivePayBanks" class="required"></select>

The meat here of the post is how we can take that resulting json data and ‘bind’ it to the bank dropdown:

success: function (positivePayBanks) {   <--- 'positivePayBanks' is the returning json data
  $("#positivePayBanks").find('option').remove();     <--- this clears it each time, as it will continue to just append if I don't first remove it!
  $banks = $("#positivePayBanks");
  $.each(positivePayBanks, function (i, bank) {    <--- the beauty of jQuery here is a nice foreach statement
   if (i == 0) { $("#BankID").val(bank.BankID); }    <-- I'm actually forced to set the id of the selected bank or the form post doesn't catch it.
   $banks.append('<option value="' + bank.BankID + '">' + bank.BankName + '</option>');   <-- append the results to the select
  });
$.unblockUI(); //unblock the UI
}

I left the blockUI in this sample because I want to remind those using ajax, that there is no control over the latency on the network – so rather than leave the user wondering what just happened, this gives a visible indicator.
For those new to Json, the part I like the best here is that jQuery will deserialize the json data into the ajax result:
(success: function (positivePayBanks))
Since this is a list of banks, we can use jQuery to loop through each one and it is represented as a bank object, which allows for the ‘bank.BankID’ and ‘bank.BankName’
Just as a finishing note, it is possible to just return a partialview with a Html.DropdownList , etc..  - however, by using Json , it greatly decreases the transmission over the wire.  Json is a perfect medium for keeping the data minimal, and as you can see it goes hand in hand with frameworks like jQuery.
One piece of this I do not like, is how I needed to then set the selected bankId to a hidden field.  I was able to get the value passed into the form collection on form post naturally.  If anyone has a trick for that- let me know  :)
PS. I’m still looking for a good WordPress application to run on MacBook

ASP.NET MVC with JTemplates – Part II

In my first part I of this two part series, I covered using Json, ASP.NET MVC, and jTemplate to bind to a simple html table.

The next part of this series is to ‘prettify’ the table using the jQuery plugin  DataTables

DataTables supports using the same theme as used by jQuery UI, so I have decided to include this as well.  Basically in about 4 lines of javascript, we can convert the previous simple table to a nice looking pageable, sortable, searchable grid!

image

The references are updated (see sample code):

    <link href="<%= Url.Content("~/Content/Site.css") %>" 
      rel="stylesheet" type="text/css" />
    <link href="<%= Url.Content("~/Content/jquery-ui-1.8.1.custom.css") %>" 
      rel="stylesheet" type="text/css" />
    <link href="<%= Url.Content("~/Content/demo_table_jui.css") %>" 
      rel="stylesheet"  type="text/css" />
    <script type="text/javascript" 
      src="<%= Url.Content("~/Scripts/jquery-1.4.1.js") %>"></script>
    <script type="text/javascript" 
      src="<%= Url.Content("~/Scripts/jquery-ui.js") %>"></script>
    <script type="text/javascript" 
      src="<%= Url.Content("~/Scripts/jquery-jtemplates_uncompressed.js") %>"></script>
    <script type="text/javascript" 
      src="<%= Url.Content("~/Scripts/jquery.dataTables.js") %>"></script>

The next step is to apply the DataTables plugin to our table.

(If you had the demo code for part I, you might notice part II I had to make sure to define the thead and tbody tags in the table.)

<script type="text/javascript">
    $(document).ready(function () {
        $.ajax({
            type:"POST",
            url: "<%= Url.Action("GetData") %>",
            data: "{}",
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function(data){
                $("#jTemplateDemo").setTemplate($("#templateHolder").html());
                $("#jTemplateDemo").processTemplate(data);

                $('#personTable').dataTable({
                    "bJQueryUI": true,
                    "sPaginationType": "full_numbers",
                    "aoColumns": [{ "sTitle": "First Name" },                                   
                       { "sTitle": "Email" }]
                });
            }
        });
    });
</script>

I have included the previous javascript – the key section is the $(‘#personTable’).dataTable.

There are tons more functionality you can get from the plugin – including grid editing, server pagination, etc…  (ie. saving state – (“bStateSave”:true)

I hope to create a third part of this series that will combine the edit features of the datatable with the ASP.NET MVC + json capability.  This will be valuable to show the posting of json data as well as updating the underlying json data source for the template.

(by the way, there is an unintended “easter egg” in this post.  If you recall the template grid TH was incorrectly labeled ‘Last Name’ instead of ‘Email’. By defining the aoColumns above, it overrides the ‘Last Name’ in the template and applies the ‘Email’ header.  aoColumns is an optional parameter in this case).

I have included this code for your review – download here

ASP.NET MVC with jTemplates – Part I

One of my goals in web development is to continue to look to use json to transmit data vs. using partial views.  Obviously by transmitting json data, the payload is going to be much more efficient.

I’m going to break this out into two parts :

Part I is going to cover the basics to using jTemplate with jQuery within an asp.net mvc environment.

Part II is going to take this concept and apply it to a nice looking jQuery plugin ‘grid control’ called  DataTables

Let’s look at what the final result will be:

image

Let’s address the server side pieces first:

I’m going to create a new Model class ‘Person’:

public class Person
    {
        public string ID { get; set; }
        public string FirstName { get; set; }
        public string Email { get; set; }
    }

Using the default asp.net mvc created project type, I’ll just a hook into the the Home controller to display the table in the index page.  To do this, I’ll need to add another action with some sample data that will be called from the page via ajax:

 

 [HttpPost]
 public JsonResult GetData()
 {
      IList<Person> people = new List<Person>
        {
          new Person {ID = "1", FirstName = "Anne", Email = "anne@domain.com"},
          new Person {ID = "2", FirstName = "Amelie", Email = "amelie@domain.com"},
          new Person {ID = "3", FirstName = "Polly", Email = "polly@domain.com"},
          new Person {ID = "4", FirstName = "Alice", Email = "alice@domain.com"},
          new Person {ID = "5", FirstName = "Martha", Email = "martha@domain.com"}
        };
      return Json(people);
}

The ‘return Json(people)’ will return the list in json format – which you can see in the above Firebug screenshot ‘response’. 

So that is basically it for the server side.

The first step in the views is to add the references to the javascript files.  Since I’m using the site.master I’ll add it there, so that it’s available to other views as well:

image 

(For production, you will want to use the compressed/min files instead)

I also add a new ContentPlaceHolder in the head of the site.master:

<asp:ContentPlaceHolder ID="HeadContent" runat="server" />

This way on the views, I can put any scripts in the head tags as well.

In the Index.aspx page we can finish this functionality:

1. add the scripts to the head of the view:

<asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server">
    <script type="text/javascript">
        $(document).ready(function () {
        $.ajax({
                type:"POST",
                url: "<%= Url.Action("GetData") %>",
                data: "{}",
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                success: function(data){
                    $("#jTemplateDemo").setTemplate($("#templateHolder").html());
                    $("#jTemplateDemo").processTemplate(data);
                }
            });
        });
    </script>
</asp:Content>

To review this (we could use a $.getJSON as well) – on the page ready function I’m going to make an ajax call back to the ‘GetData’ action.  This is defined in the ‘url:’ parameter.

In this case there are no parameters being passed so the data is left blank (this is best practice to include “{}” when blank).  It is possible to use a REST url as well with parameters.

We define out contentType (using $.getJSON) would do this automatically.

Lastly, we provide an ‘onSuccess’ function – the ‘data’ will contain the returning Json from our action call.  The next two calls use the jTemplate API to merge the Json data to the templated html, as shown below.

2. add the template to the view:

<script type="text/html" id="templateHolder">
    <table border="1">
    <tr>
        <th>
            First Name
        </th>
        <th>
            Email
        </th>
    </tr>
    {#foreach $T as record} 
        <tr>
            <td>
                {$T.record.FirstName}
            </td>
            <td>
                {$T.record.Email}
            </td>
        </tr>
    {#/for}
</table>
</script>
    
<div id="jTemplateDemo">
</div>

 

One thing to keep in mind is to put this html in the script tag.  Alternatively you could load this template from another file as well.

With this approach we have created a very lightweight approach to passing data from the server to the client – the binding to the template occurs on the client.  If we used partial views, the binding process would occur on the server and transmit the payload with the html, increasing it’s size.  The lightweight json approach is critical especially in our ajax calls

Next post we’ll take this table and convert it into a ‘DataTable’.

I have included this code for your review – download here

Moving to JSON with Client Side Templating for Views

I was Google ‘Buzzing’ today on this and figured I’d post the same here :

My new frontier in asp.net mvc (and hopefully asp.net 4) will be implementing templates and moving to a more rich client ‘json’ experience vs. partials views.

couple of resources:

http://www.west-wind.com/Weblog/posts/509108.aspx

http://weblogs.asp.net/dwahlin/archive/2009/04/17/minimize-code-by-using-jquery-and-data-templates.aspx

http://weblogs.asp.net/dwahlin/archive/2009/05/03/using-jquery-with-client-side-data-binding-templates.aspx

http://starterkit.jsonfx.net/

http://jbst.net/

The Telerik MVC controls use JSON I think behind the scenes.  They have source code – I am interested in evaluating that as well. (I’m using their controls, I mean evaluate as in see the source and how they implement their controls with JSON – in particular their grid control)

What you might appreciate here is that you could, in theory, use this approach as your view for any backend framework.

Also, I know ExtJS has some rich controls, they are all Json related, I think Phil Haack had an article on using mvc with ext.

Basically, today, if you add for example, an item to a ‘grid’, I go behind the scenes, add it – then redisplay the grid.  In these approached, you’d literally just append a row to the grid instead.  Very interesting.   The value is going to be less traffic, as partial views create more traffic.

I see this as well:
ASP.NET AJAX And Client-Side Templates by Dino Esposito:
http://msdn.microsoft.com/en-au/magazine/cc546561.aspx

The HTML Message Pattern by Dino Esposito:
http://msdn.microsoft.com/en-au/magazine/cc699560.aspx

Of course, this all assumes you opt for a rich experience with jSON/jQuery vs. something like Flex or Silverlight  :)

Using jQuery with ASP.NET Webforms – Validation

This isn’t to be a big post on how to use everything here, but I was asked last night to help someone out with a validation requirement and they wanted to use jQuery with asp.net webforms.  Figured I’d post how I handled it.’

First, I did want to try to address the ‘mangled id’s’ – or rather the INamingContainer with it’s auto-generated IDs. (supposedly being addressed in .net 4.0 ?)

John Sheehan’s blog posted a  suitable solution to get me started:

        String.prototype.endsWith = function(str) {
            return (this.match(str + '$') == str)
        }

        jQuery.expr[":"].asp = function(a, i, m) {
            return (id = jQuery(a).attr('id')) && id.endsWith(m[3]);
        };

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

(This can go in the script tag at the top of the page)

What this does is allow us to use some custom jquery selector functionality.  An example is if I had a checkbox control:

<asp:CheckBox ID="cbTest" runat="server"  Text="Check"  />


I can use jquery to determine if it’s checked or not:

$(":asp('cbTest')").attr('checked')

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Ok, let’s get to the problem at hand:  The goal is use asp.net validators, but only fire them if the ‘cbTest’ checkbox is checked.   Additionally, when it’s checked or unchecked, it should also fire instantly to determine what should be validated.

To do this, I needed to better understand how asp.net webform validators work.  Luckily, not only did I find some information, but information with jquery on Simone Chiaretta’s blog post on ‘How to manage asp.net validation from javascript with jquery ‘

Couple of gems: there are some javascript functions we have available to us when using asp.net webforms:

ValidatorEnable is the one I’m interested in here:

ValidatorEnable($("#<%= valEncOtherMimetypeRequired.ClientID %>")[0], true);


This is good, just what I needed.  However, due to concerns with master pages, etc… I was able to use the custom selector logic instead:

ValidatorEnable($(":asp('FirstNameVal')")[0], true);
 

(note, the [0] is to to get the real DOM element and not the jQuery wrapper around it.)

That is enough to get me started then:

Simple example is we have a dropdown and a textbox.  When the checkbox is clicked, it validates.  If it’s unchecked it turns off the validation.

Here is the html:

<form id="form1" runat="server">
    <div>
        Type
        <asp:DropDownList runat="server" ID="ddl"></asp:DropDownList>
        <asp:CustomValidator runat="server" ID="rfv" ControlToValidate="ddl"
            ClientValidationFunction="RequiredDropDownCheck"
            ErrorMessage="*" />
        <asp:CheckBox ID="cbTest" runat="server" Text="Check" />
        <asp:TextBox ID="FirstName" runat="server"></asp:TextBox>
        <asp:CustomValidator runat="server" ID="FirstNameVal"
            ControlToValidate="FirstName"
            ClientValidationFunction="RequiredFirstNameCheck"
            ErrorMessage="*"
            ValidateEmptyText="True" />
        <br />
        <asp:Button ID="Button2" runat="server" Text="Button" OnClick="Button2_Click" />
    </div>
    </form>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }


(Messy, but this is what I received minus the validators – lol)

Now, the javascript in the head tag:

<script src="jquery-1.3.2.min.js" language="javascript" type="text/javascript"></script>

    <script type="text/javascript">
        String.prototype.endsWith = function(str) {
            return (this.match(str + '$') == str)
        }

        jQuery.expr[":"].asp = function(a, i, m) {
            return (id = jQuery(a).attr('id')) && id.endsWith(m[3]);
        };

        function RequiredFirstNameCheck(sender, args) {
            if ($(":asp('cbTest')").attr('checked')) {
                if ($(":asp('FirstName')").val().length == 0) {
                    args.IsValid = false;
                    return;
                }
            }
            args.IsValid = true;
        }

        function RequiredDropDownCheck(sender, args) {
            if ($(":asp('cbTest')").attr('checked')) {
                if ($(":asp('ddl')").val() == 0) {
                    args.IsValid = false;
                    return;
                }
            }
            args.IsValid = true;
        }

        $(function() {
            $(":asp('cbTest')").click(function() {
                if ($(":asp('cbTest')").attr('checked')) {
                    ValidatorEnable($(":asp('FirstNameVal')")[0], true);
                    ValidatorEnable($(":asp('rfv')")[0], true);
                }
                else {
                    ValidatorEnable($(":asp('FirstNameVal')")[0], false);
                    ValidatorEnable($(":asp('rfv')")[0], false);
                }
            });
        });

    </script>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

Just as a reference, I initially had “$(":asp(‘cbTest’)").change(function() {“, but IE didn’t recognize it, so I had to use the click event instead.  Not really ideal, but what can I say.

I’m sure there might be better ways to handle this, but it was interesting to see jQuery working with asp.net validators!

( More information on jQuery selectors: http://docs.jquery.com/Selectors and asp.net validation controls: http://www.codeproject.com/KB/validation/aspnetvalidation.aspx )

jqModal Tips – ajax dynamic dialogs

I’ve been using jqModal to handle all my dialog ‘window’ forms on a current application.  I’m not going to get into all the details here, but rather expand on a few complex operations.

First, one powerful aspect of jqModal is the ability to assign a dialog based on a href trigger link.

Here is an example of what this means:

$(‘.dialogs’).jqm({ajax:’@href’,modal:true, trigger: ‘a.triggerLink’});

ajax

If passed, dialog contents will be loaded remotely via ajax. You can pass the URL (e.g. $.jqm({ajax:’remote/dialog.html’}) or extract it from an attribute of the triggering element. For instance, $(.jqm({ajax:’@href’}) would grab contents from bar.html if the triggering element was <a href=”foo/bar.html”>Open Dialog</a>. If a more complicated loading routine is desired, the onShow() callback should be leveraged.

So, let’s say you have the above as described where you want to open a dialog for a list of items : the above dialog contains the very important trigger reference that is saying ‘any a href with class ‘triggerLink’ will fire an event to open the dialog.

Then, the added functionality is ‘when this happens, it’s going to call to the href of that trigger to determine the ajax form to load.

Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie.  myform.html.   I could just do the following:

$('.dialogs').jqm({ajax:'myform.html',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

When the trigger link is clicked ie. a href=”#” class=”triggerLink”  (brackets removed) it will open a dialog with the myform.html as it’s content.

This works particularly well with something like asp.net mvc.  ie. my system is to use a ascx (a snippet of html basically) that is loaded by calling a controller action.   Let’s say I have a html form that I want in the dialog.  The href will need to point to that html…. ie. mycontroller/myaction/1

so if you had a list of links you have one jqm assigned:

$('.dialogs').jqm({ajax:'@href',modal:true, trigger: 'a.triggerLink'});

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

With the corresponding html links:

<a href=”mycontroller/myaction/1” class=”triggerLink”>Item 1</a>
<a href=”mycontroller/myaction/2” class=”triggerLink”>Item 2</a>
<a href=”mycontroller/myaction/3” class=”triggerLink”>Item 3</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

the controller action, based on the parameter passed with know, for instance, that you are selecting a particular item based on id to edit inside the dialog.

So, my last ‘issue/problem’ was – ‘what if I want to have this fire based on a select’ ?

Tricky but very doable:

take the above href – assign an id to it:

<a id=”editProviderLink” href=”#” class=”triggerLink”>Edit</a>

I also have a select with id ‘employeeProviderList’.  So, you select a provider name in a dropdown, and click the ‘edit’ href link

then, in the script (document.ready):

$("#editProviderLink").click(function(event) { 
        $(this).attr("href", "/MyController/MyAction/" + $('#employeeProviderList').val()); 
    });

 

this code will do the following:

when you click on the link, it will create the href attribute of the link, injecting in the url to call via ajax – this will occur before the jqmodal will fire (thankfully) – and open up the dialog with the corresponding html returned from the controller action.   This also can be done through the ‘onShow’

onShow (callback)

Called when a dialog is to be shown. Be sure to show (set visible) the dialog.

// onShow : show+make the window translucent
var myOpen=function(hash){ hash.w.css(‘opacity’,0.88).show(); };
$(‘#dialog’).jqm({onShow:myOpen});

Be sure to check out all the callback options!

There is a way as well to fire off a callback that will occur when the dialog is closed – which I sometimes do to update the underlying page via another ajax call  :)

Hope this helps – its a bit complex, but once you dig into jqModal, it can very powerful – and especially with a MVC setup (like asp.net mvc).

An example that I will cover later is to create a html helper that encapsulates the logic to build a window.  ie.

<%= Html.jqmAjaxWindow<ClaimsController>("addDependentCareWindow","a.addDependentCareTrigger", 
    "Add Provider",true, c => c.LoadNewProviderView(ViewData.Model.Employee.Employeeid.ToString()), 
        new Hash(onHide=> "myClose"))%>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This dialog can be triggered with:

<a href="#" class="addDependentCareTrigger">Add</a>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

To get an idea of this helper code:

 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

public static string jqmAjaxWindow<TController>(this HtmlHelper helper, string dialogWindowName, string dialogTriggerName, 
           string dialogTitleText, bool isModel, Expression<Action<TController>> theAction, IDictionary options) 
           where TController : Controller 
        { 
            var sb = new StringBuilder(); 
            BuildChrome(sb, dialogWindowName, dialogTitleText); 
            sb.Append("<div class="jqmTarget clear"><p>...Loading Content...</p></div>"); 
            sb.Append("</div>"); 
            sb.Append("<script type='text/javascript'>"); 
            sb.Append("$(function() {"); 
            sb.AppendFormat("$('#{0}').jqm(", dialogWindowName); 
            sb.Append("{ajax: "); 
            sb.AppendFormat("'{0}', ", LinkBuilder.BuildUrlFromExpression<TController>(helper.ViewContext.RequestContext, 
                helper.RouteCollection, theAction)); 
            if (isModel) 
            { 
                sb.Append("modal: true, "); 
            } 
            foreach (DictionaryEntry option in options) 
            { 
                sb.AppendFormat("{0}:{1},", option.Key, option.Value); 
            } 
            sb.Append("target:'div.jqmTarget', "); 
            sb.AppendFormat("trigger:'{0}'", dialogTriggerName); 
            sb.Append("});"); //end of jqm 
            var browser = HttpContext.Current.Request.Browser; 
            if (browser.Browser != "AppleMAC-Safari") 
            { //problem with drag and chrome... 
                sb.AppendFormat("$('#{0}').draggable();", dialogWindowName); 
            } 
            sb.Append("});</script>"); //end of function() 
            return sb.ToString(); 
        }
 
private static void BuildChrome(StringBuilder sb, string dialogWindowName, string dialogTitleText)
        {
            string imagePath = VirtualPathUtility.ToAbsolute("~/Content/Images/Close.jpg");
            sb.AppendFormat("<div id="{0}" class="jqmWindow">", dialogWindowName); //outer window
            sb.Append("<div class="jqmTitleContainer jqDrag">");

            sb.AppendFormat("<div class="jqmTitle">{0}</div>", dialogTitleText); //title
            sb.Append("<div class="jqmCloseContainer">"); //start close container
            sb.AppendFormat("<a href="#" class="jqmClose"><img class="jqmCloseImage" src="{0}" 
               alt="Close"/></a>", imagePath);
            sb.Append("</div>"); //end close container
            sb.Append("</div>"); //end jqmTitleContainer
        }

jQuery Tip with Select/Options

Although quite ‘simple’ – it seems I always forget the exact syntax here  :)

So this is mostly a reminder post for myself!

To get the value of a select:

$('#select').val();

To get the text of the selected option:

$('#select :selected').text()
 
 

jQuery CheckBoxes

Working with selecting and unselected a group of checkboxes in jQuery can be a tad tricky.

But it appears you must use the attr to set it as shown below:

For simplicity sake, let’s say I have a list such as

Select All   Select None
[ ] Company A
[ ] Company B

Initially tried to just set the checkbox checked to true/false directly, ie. $(this).checked = true

$(“#selectAll”).click(function() {
$(“input:checkbox”).each(function() {
$(this).checked= true;
});
});

This did not work as expected.

This does works:

$(“#selectAll”).click(function() {
$(“input:checkbox”).each(function() {
$(this).attr(‘checked’, true);
});
});

$(“#selectNone”).click(function() {
$(“input:checkbox”).each(function() {
$(this).attr(‘checked’, false);
});
});

jQuery 1.3 Released

Some great new stuff added to jQuery – please welcome in jQuery 1.3 !

Details here

I’ll be digging in soon to update my sites with this latest version and report back any gotchas.

There is a note about validation library updated for 1.3, and I use that one – so will have to test all that out.

Two jQuery Links for the Christmas Season

Two good jQuery links for the Christmas season:

1. A fantastic ‘Improve your jQuery – 25 excellent tips’ by Jon Hobbs-Smith – and these are excellent tips! 

I found the internal ‘data’ method to store state to be interesting – as well as the idea of using classes to store state – very cool approach!

2. jQuery Cheat Sheet   ( direct png link )

Have a Merry Christmas!

Post Navigation

Follow

Get every new post delivered to your Inbox.