Showing posts with label mvc. Show all posts
Showing posts with label mvc. Show all posts

Saturday, August 18, 2012

Using Less and Twitter Bootstrap in ASP.NET MVC4

UPDATE 05/02/2013:

Changed ScriptBundle and StyleBundle to just Bundle, per Andrey Taritsyn:
Bundle Transformer it is not recommended to use together with the StyleBundle and ScriptBundle classes, because these classes already contain transformations (instances of the built-in minifiers: CssMinify and JsMinify). Use a Bundle class.

UPDATE 11/08/2012:
  1. Create a new MVC4 Internet Application
  2. Add the following Nuget Packages
  3. Rename /Content/site.css to /Content/site.less 
    • Edit BundleConfig.cs in the App_Start folder and update the css file name to site.less like so:
      bundles.Add(new var cssTransformer = new CssTransformer();
      var jsTransformer = new JsTransformer();
      var nullOrderer = new NullOrderer();
      
      var defaultScriptsBundle = new Bundle("~/bundles/default.js").Include(
                  "~/Scripts/jquery-{version}.js",
                   "~/Scripts/jquery-ui-{version}.js",
                  "~/Scripts/site.js");
      defaultScriptsBundle.Transforms.Add(jsTransformer);
      defaultScriptsBundle.Orderer = nullOrderer;
      bundles.Add(defaultScriptsBundle);
      
      var defaultStylesBundle = new Bundle("~/Content/default.css").Include("~/Content/site.less");
      defaultStylesBundle.Transforms.Add(cssTransformer);
      defaultStylesBundle.Orderer = nullOrderer;
      bundles.Add(defaultStylesBundle);
      
    • Add the following to the top of /Content/site.less in order to have access to all of the Bootstrap mixins:
      @import "less/bootstrap.less"; 
      body {
            padding-top: 60px;
            padding-bottom: 40px;
      }
      @import "less/responsive.less"; 
      

    =================== THE REST OF THIS POST IS OUT OF DATE ==========

    UPDATE 8/20/2012: I've created a Nuget package that performs the steps below. I'd suggest reviewing what the package does below and then running:
    Install-Package Twitter.Bootstrap.Less.MVC4

    ASP.NET MVC4 has a great new feature that can bundle and minify your CSS and Javascript files.

    But in order to get Twitter Bootstrap to work it takes a bit more work. Here are the steps that worked for me.

    1. Create a new MVC4 Internet Application
    2. Add the following Nuget Packages
    3. Create an Infrastructure folder and add the following two files: (hat tip to this Stackoverflow question)
    4. Rename /Content/site.css to /Content/site.less 
    5. Edit BundleConfig.cs in the App_Start folder and replace the default Content/css bundle with the following:
      var css = new Bundle("~/Content/css").Include("~/Content/site.less");
      css.Transforms.Add(new LessMinify());
      bundles.Add(css);
      

    6. Add the following to the top of /Content/site.less in order to have access to all of the Bootstrap mixins:
      @import "less/bootstrap.less";
      

    If you have "shared" .less files from other projects I found importing them in site.less right after boostrap.less to work pretty well. They'll have access to all the mixins.
    @import "less/bootstrap.less";
    @import "less/shared.less";
    

    The completed solution is available on Github here

    If there is a better/easier way to do this please let me know in the comments!




    Sunday, February 20, 2011

    Preserve Telerik MVC Grid Checkboxes When Paging

    This article explains how to preserve the state of input checkboxes in a Telerik ASP.NET MVC Grid control when paging, sorting, and filtering. This solution only works for client side Data Binding. If you're using Server Side Data Binding you'll need to come up with a different solution.

    I'm a big fan of the Grid control. It's a real time saver and fills in a big gap that ASP.NET MVC is missing over WebForms!

    The first step is to maintain a list of checkbox states. Below is the client side javascript you'll need to add to the page that has your MVC Grid. Note, jQuery is required for this to work.

    var selectedIds = [];
    
    $(document).ready(function () {
        //wire up checkboxes.
        $('#YOUR_GRID_ID').on('change', ':checkbox', function (e) {
            var $check = $(this);
            //console.log($check);
            if ($check.is(':checked')) {
                //add id to selectedIds.
                selectedIds.push($check.val());
            }
            else {
                //remove id from selectedIds.
                selectedIds = $.grep(selectedIds, function (item, index) {
                    return item != $check.val();
                });
            }
        });
    });
    

    NOTE: You'll want to change YOUR_GRID_ID to match what you set your Grid's Name to.

    The code above uses the global variable selectedIds to store the values of each selected checkbox in the grid. I use the jQuery live method to attach the change event to every checkbox in the grid. The nice thing about live is that it will catch new checkboxes that are loaded when paging, filtering, or sorting.

    The next step is to restore the checkbox states after each ajax request that changes the grid.

    function onDataBound(e) {
        //restore selected checkboxes.
        $('#YOUR_GRID_ID :checkbox').each(function () {
            //set checked based on if current checkbox's value is in selectedIds.
            $(this).attr('checked', jQuery.inArray($(this).val(), selectedIds) > -1);
        });
    }
    

    NOTE: You'll want to change YOUR_GRID_ID to match what you set your Grid's Name to.

    I use the Grid's OnDataBound client side event, which fires after the Grid is finished loading new data, to parse threw all the new checkboxes and set their checked state based on if their value is in our selectedIds global variable.

    Add the .ClientEvents line below to wire up the onDataBound event:

    @(Html.Telerik().Grid<Web.Models.YOURMODEL>()
        .Name("VideosGrid")
        .ClientEvents(events => events.OnDataBound("onDataBound"))
    )
    

    If this helped you or you have a suggestion to improve it, let me know via the comments!