3

I'm trying to determine the best way to structure my application so that I don't get a lot of javascript splattered all over the place.

I have an ASP.NET MVC application with a view which loads a sllooooowwwww partial view using Michael Kennedy's approach to Improve perceived performance of ASP.NET MVC websites with asynchronous partial views. The partial view itself is rendering a DataTables grid (which has its own CSS/JS files), as well as Javascript-based configuration for the grid itself (column formatting, sorting defaults, editor configuration, etc).

My question is what is a clean way to structure and maintain all this? I have at least 3 varieties of scripts (CSS and/or JS) involved here:

  1. The JS on the main view which loads the partial view.
  2. The CSS/JSfiles for DataTables
  3. The JS inside the partial view which runs on $(document).ready() and configures that particular grid.

I can control (on the main view) where the CSS/JS are rendered using Razor's @section for scripts/styles (Item #1 above). However, a partial view can't take advantage of the @section functionality, so any CSS/JS in a partial view gets injected into the middle of the page. That doesn't really set well with me, because then the rendered HTML looks all nasty with CSS/JS showing up in the middle of the main view. I know things like Cassette can help with Item #2 when the CSS/JS are all stored in external files.

But what about Item #3 where I have CSS/JS which is very specific to that partial view? It may be things as small as attaching click event handlers for the view or configuring JQuery plugins, but does that mean I should separate that out into another JS file? I don't like separating these things if I don't need to, especially the grid configuration for each partial view.

In my case, I have an application with several views containing these partial views which render grids, and none of the grids contain the same set of columns - so the JS configuration for each grid is different which runs on $(document).ready().

David McClelland
  • 2,686
  • 4
  • 28
  • 37

2 Answers2

2

I would consider not using partial views at all, for the reasons that you mentioned. Instead of loading partial views with ajax, load json data from controller. Use JavaScript template like handlebars.js to get the razor effect on the client side. Much cleaner. Smaller http payload.

CodeToad
  • 4,656
  • 6
  • 41
  • 53
  • Thanks for that idea - I will look into handlebars.js, do you have any resources which have a proof-of-concept for ASP.NET MVC web applications which use handlebars.js? Also (just for argument's sake), let's say I wanted to stick to Razor templates for partial views - what's a good way to organize the Javascript used inside the partial views themselves? – David McClelland Jan 15 '14 at 14:07
  • Sorry David but I Don't have either. If this is a new project, you might want to consider the approach of using the server to return bare data through rest API only, no UI in server. no server pages, no .cshtml at all. on the client side, static html pages get JSON from server, and generate ui from the data using templates/ client side MVC such as ember or angular. Done this way, you have nice separation between server and client, It matters not to the client what the server is, and vice versa. client could eventually be non-html such as a native smartphone app. – CodeToad Jan 15 '14 at 14:46
1

I had a similar situation using JQGrid. I ended up with JavaScript up the wazoo on any view that used the grid. My solution was to put any of the heavy-lifting javascript into external files, and namespace them like this:

var JqGridHelper = JqGridHelper || {};
JqGridHelper.SetupGrid = function (gridTable, pager, gridJson, colNameJson, colModelJson, label, rowNum, gridCompleteFunc, columnChooser) {
    gridTable.jqGrid({
        datatype: "local",
        data: gridJson,
        colNames: colNameJson,
        colModel: colModelJson,
        rowNum: rowNum,
        autowidth: true,
        height: '100%',
        pager: pager,
        sortname: 'id',
        viewrecords: true,
        sortorder: "desc",
        caption: label,
        gridComplete: gridCompleteFunc
    });

    gridTable.jqGrid('navGrid', pager, { edit: false, add: false, del: false });
    if (columnChooser == true) {
        JqGridHelper.AddColumnChooser(gridTable, pager, function() {

        });
    }

};

Try to abstract as much of the reusable DataTable binding and initialization code, then just call your abstracted methods from the JavaScript on the partial views.

If you go the way of external javascript files, be sure that you're loading them at the appropriate time, rather than loading them all on the initial page-load.