Archive

Archive for the ‘MVC’ Category

Tip: Using Spark Conditionals to Toggle CSS and JavaScript

January 3, 2012 Comments off

The conditional attribute is a fantastic shortcut to toggle CSS, input boxes, and other elements on a page–and is something I don’t see used in very many examples. One of my favorites is applying classes to an element based on a output model property, such as a permission boolean.

Here’s an example.

In a recent project, a dashboard screen had several charts that toggled on and off based on the user’s preference. Rather than rebuild the screen each time, each class simply toggled an ‘enabled’ class based on a Model.{Property}.

<div class="charts">
    <div id="enteredbycount" class="loading enabled?{Model.ShowEnteredBy}"
		style="inlineChart">
	</div>
    <div id="schoolcount" class="loading enabled?{Model.ShowSchoolCount}"
		style="inlineChart">
	</div>
</div>

The Spark Conditional only renders the text preceding the conditional ?{} if the condition is true. In this example, if our Model.ShowSchoolCount returns false, enabled never renders and our chart (due to some styling), remains hidden and never posts back to the server to get the chart data (saving an unnecessary AJAX call).

By toggling a class, you can trigger a certain set of styles, events using JavaScript, or most anything else you can dream up.

Quick Solution Generation using PowerShell: New-Project

February 13, 2011 1 comment

When I have an idea or want to prototype things, I tend to mock it up in Balsamiq, then dig right in and write some specs to see how it’d work.  Unfortunately deleting the junk Class1.cs in Library projects, the plethora of excess in MVC3 webs, and such tends to be the most time intensive part of wiring up a quick project in .net.

All that deleting is too many steps–especially if you’re developing on the fly with a room of folks. I needed something ala command line to fit my normal workflow:

  1. o init-wrap MyProject -git
  2. cd MyProject
  3. git flow init
  4. {something to create projects, solutions, etc}
  5. o init-wrap -all
  6. {spend 5 minutes cleaning up junk files in my way}

Introducing New-Project

Yes, I know. I’m not a marketing guru. I don’t have a cool name for it.  Just a standard PowerShell convention.

Usage:

  -Library { } : Takes a string[] of names for c# class libraries to create.

  -Web { } : Takes a string[] of names for MVC3 web projects to create.

  -Solution "" : Takes a single string for your solution name.

Example:

New-Project -Library MyProj.Core, MyProj.Specs -Web MyProj.Web -Solution MyProject

SiteScaffolding

 

What does this all do?

Well, honestly, I’m not sure how ‘reusable’ this is… the projects are pretty tailored.

Libraries

  • Libraries don’t have the annoying Class1.cs file that you always delete.
  • AssemblyInfo.cs is updated with the specified Name and Title.

MVC3 Webs

  • The web.config is STRIPPED down to the minimal (27 lines).
  • The folder structure is reorganized (removed unnecessary folders, like Controllers, which I put in libraries, not the web project).

Solution

  • This is the only one I’m actually using the VisualStudio.DTE for–it makes it super easy to create and add projects into the solution.

But there are other scaffolding systems out there–why not use them?

Most of the time, I don’t need a full system. I don’t need my objects mapped, views automatically set up, or anything else. 

Start with three empty projects, load up the Specifications project, and start driving out features.  That’s how it’s supposed to work, right?  So why would I want to have to pre-fill my projects ahead of time?

 

What’s next?

  • Error catching and handling (it’s pretty lax right now)
  • Handle setting up gitflow, openwrap, jQuery, etc. Less typing good!
  • Something… who knows. :D

 

Where to get it?

I’ve tossed it up on github at https://github.com/drlongnecker/New-Project.  Right now it has the WOMM warranty.

6a0120a85dcdae970b0128776ff992970c

TableSorter – Creating a Custom ‘TimeSpan’ Parser

October 22, 2010 Comments off

Activities ordered incorrectly by string comparison.In an application we’re working on, I needed a way to sort a string-based time span returned by my view. The problem was separating it out so that AMs came before PMs.

tablesorter allows adding custom parsers to columns. Along with a simple regular expression, the parser can swap the time format around (AM 10:30 rather than 10:30 AM) and sort accordingly.

The custom parser code:

 
$.tablesorter.addParser({ 
    id: 'timeSpan', 
    is: function (s) { return false; }, 
    format: function (s) { 
        var re = /([0-2]?[0-9]:[0-5][0-9])|(AM|PM)/; 
        var matches = re.exec(s); 
        return matches[0,1] + " " + matches[0,0]; 
    }, 
    type: 'numeric' }); 

Adding the parser into TableSorter:

$('#my-table').tablesorter({ 
    sortList: [[1, 0], [0, 0]], 
    headers: { 
        0: { sorter: 'timeSpan' }, 
        1: { sorter: 'dayOfWeek' }, 
        6: { sorter: false } 
    }, 
    widgets: ['zebra'] 
}); 

Now, everything looks like it should:

Activities ordered correctly by start time.

Categories: JavaScript, MVC Tags: , ,

Using .less To Simplify BluePrintCSS

December 17, 2009 2 comments

For the past few projects, I’ve used BluePrintCSS and really liked the experience.  It forced me both to conquer my CSS layout fears (tables no more) and standardize a few of my formatting techniques that we use on our internal and external applications.  Good deal all around.

The one caveat that I really… really didn’t like was how I had to name things.

The clean class codes and IDs that I had…

<div class="page">
    <div class="header">
        <div class="title">
            <h1>${H(ApplicationName)}</h1>
        </div>
        [...]
    </div>
</div>

Turned into long, drawn out classes…

<div class="container">
    <div class="span-24">
        <div class="prepend-1 span-12 column">
            <h1>${H(ApplicationName)}</h1>
        </div>
    </div>
</div>

Without the BluePrintCSS guide or the CSS files available, you couldn’t look at the classes and tell much of what was going on… and it wasn’t descriptive like ‘header’ and ‘title’.

Welcome To .less (dotless)

I stumbled onto .less (aka dotless, dotlesscss, that shizzle css thingy) back in November and thought “hey, that’s cool… that’s how CSS should work” and didn’t give it much more thought.  Shortly after fav’ing it in github, I noticed they pushed an update targeting BluePrintCSS operability.  Cool–I’ve GOT to try this out.

Getting Started with .less

The instructions on the home page (right side of the screen) is all you need.  Clone, compile, update web.config and start go!

The Benefits

So what’s the big hype?  This:

1. Import your BluePrintCSS file into your .less file (for me, it’s site.less).

@import “screen.css”;

2. Simply reference any of the BluePrintCSS class styles as part of your custom styles.

#header {
    #title {
        .span-10;
        .column;
    }
 
    #menucontainer {
        .span-14;
        .column;
        .last;
        text-align: right;
    }
}
 
#left-content {
    .span-18;
    .column;
}
 
#right-boxes {
    .span-6;
    .column;
    .last;
}

Then a miracle occurs...3. “Then a miracle occurs…”

When dotless’ HttpHandler hits your .less file (or your use dotless.Compiler), it translates those referenced styles into their actual CSS tags.


#header #title{width:390px;float:left;margin-right:10px;}

Nice.  Plain and simple (and miraculous).

Lessons Learned

Some “lessons learned” so far:

1. Order matters.  Referencing a style before you’ve ‘created’ it will bork the interperter. So @imports always go at the top and if you’re referencing within the same .less file, keep things in order.

2. Pre-compiling is fun.  For now, I’m pre-compiling my .less files without using the handler and simply sending the css file up to our web server.  This is easily taken care of with either a MS Build task or psake task.  Here’s how an example of a quick MS Build task that references the dotless.Compiler in the solution’s “tools” directory.

$(SolutionDir)Tools\dotLess\dotless.compiler.exe -m $(ProjectDir)content\css\site.less $(ProjectDir)content\css\site.css

3. .less files need to be ‘Content’. Since VS2008 is stupid, .less files (like .spark views, etc) need to be explicitly set to have a Build Action of ‘Content’ so that the publishing process sends them up to the web server.  If you’re publishing via psake or another automation tool, then ignore this. ;)

That’s it for now.  Hit up the project site, peruse and clone the github repo, and join the discussion for .less and (finally) start applying some DRY to your CSS.

Reusable ‘Controls’ with Sprites, CSS, and Spark Partials

October 2, 2009 Comments off

I came across SilkSprite during some of my work with BluePrintCSS and fell in love.  I’ve used the FamFamSilk icons for ages and, with a current project, wanted to implement some instant CSS buttons and menu items using those icons.

So, with CSS-fu in hand, here’s how the button turned out.

First, creating a simple CSS button style:

.button

{

    display: inline-block;

    font-weight: bold;

    font: bold .85em/2.5em Verdana, Helvetica, sans-serif;

    text-decoration: none;

    text-indent: 10px;

    width: 150px;

    height: 2.5em;

    color: #555555;

    background-color: #EAEAD7;

    border: #CCCCCC solid 1px;

    -moz-border-radius: 5px;

    -webkit-border-radius: 5px;

}

 

.button:hover

{

    background-color: #F3F3E9;

    color: #737373;

    cursor: pointer;

}

This button is pretty simple and standard—nothing fancy.  The most important tag in there is display: inline-block as this allows our buttons to share the same row and not stack on top of each other (like float:left would cause).

Hover Off: CSS Button - Hover Off

Hover On: CSS Button - Hover On

Second, because I needed to include the icon INSIDE another container (the button), I modified the original SilkSprite ss_sprite and removed a bit of the extra padding.

.sprite

{

    display: inline-block;

    overflow: hidden;

    background-repeat: no-repeat;

    background-image: url(/content/img/sprites.png);

    padding-left: 25px;

    padding-top: 2px;

    height: 16px;

    max-height: 16px;

    vertical-align: middle;

}

The important thing to note here is the padding-top and the height attributes.  Until I’m lead into the light and improve my CSS-fu, I’m compensating for the font height differences by using padding-top.  e.g. I want the icon to truly show up in the “middle”… and vertical-align just wasn’t pushing it far enough.

We’ll come back to actually working with SilkSprite in a moment, let’s work up a quick Spark partial view to display our results.  Now, you could do this without the partial views—just replace my Spark variables with the actual text we’re passing to them.  I’ll provide both examples.

Our button needs three elements to be useful:

  1. An ID so that we can call it from jQuery or your client-side query engine of choice,
  2. A Sprite Name, such as ss_add, etc.  These are provided by SilkSprite.
  3. The button text.

So, knowing that, a basic button could be rendered using:

<div id=”my-button” class=”button”>

    <span class=”sprite ss_add” />Add Activity

</div>

We can simply substitute out the variable elements (id, sprite class, and text) and create a Spark partial view (named _styledButton.spark and located in the /Shared view folder).

<div id=”${id}class=”button”>

    <span class=”sprite ${sprite}“></span>${text}

</div>

In our views, it’s easy to create a button:

<styledButton text=”‘Add Activity‘” id=”‘my-button‘” sprite=”‘ss_page_add‘” />

Note: You need to surround your text with single quotes (‘text’) to inform the Spark engine that the information contained in your variables is a string.

Now, we have shiny, icon’d buttons:

Hover Off:

Hover On:

Categories: HTML, MVC, Spark View Engine

Populating Select Lists in ASP.NET MVC and jQuery

September 25, 2009 Comments off

I’ve been working the last bit to find the best way to create/populate select (option) lists using a mixture of ASP.NET MVC and jQuery.  What I’ve run into is that the “key” and “value” tags are not passed along when using Json(data).

Here’s what I’m trying to pull off in jQuery: building a simple select drop down list.

var dd_activities = “<select id=’dd_activities’>”;
var count = data.length;
for (var i = 0; i < count; i++) {
 dd_activities += “<option value='” + data[i].Key + “‘>” + data[i].Value + “</option>”;
}
dd_activities += “</select>”;

$(“#activities”).before(dd_activities);

Using some very basic key/value data:

[
 {"3","Text Value"},
 {"4","Another Text Value"},
 {"1","More boring values..."},
 {"2","Running out of values"},
 {"5","Last value..."}
]

Without any sort of name, I was at a loss on how to access the information, how to get it’s length, or anything.  FireBug was happy to order it up… but that didn’t help.
 
My first attempt was to use a custom object, but that just felt dirty—creating NEW objects simply to return Json data.
 
My second attempt matched the mentality of newing new anonymous Json objects and seemed to work like a champ:
 

[Authorize]

[CacheFilter(Duration = 20)]

public ActionResult GetActivitiesList()

{

    try

    {

        var results =

        _activityRepository

            .GetAll()

            .OrderBy(x => x.Target.Name).OrderBy(x => x.Name)

            .Select(x => new

                {

                    Key = x.Id.ToString(),

                    Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

                })

            .ToList();

 

        return Json(results);

    }

    catch (Exception ex)

    {

        return Json(ex.Message);

    }

}

 
Well, not beautiful, but returns a sexy Key/Value list that Json expects—and that populates our select list.
[
 {"Key":"3","Value":"Text Value"},
 {"Key":"4","Value":"Another Text Value"},
 {"Key":"1","Value":"More boring values..."},
 {"Key":"2","Value":"Running out of values"},
 {"Key":"5","Value":"Last value..."}
]
The next step was to get that out of the controller and into the data repository… pushing some of that logic back down to the database.
 

var criteria =

    Session.CreateCriteria<Activity>()

    .CreateAlias(“Target”, “Target”)

    .Add(Restrictions.Eq(“IsValid”, true))

    .AddOrder(Order.Asc(“Target.Name”))

    .AddOrder(Order.Asc(“Name”))

    .SetMaxResults(100);

 

var data = criteria.List<Activity>();

var result =

    data

        .Select(x => new

            {

                Key = x.Id.ToString(),

                Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)

            })

        .ToList();

tx.Commit();

return result;

 
A bit of formatting, restrictions, push the ordering back to the database, and a tidy SQL statement is created.
 
The last touch is the return type.  Since we’re returning a “List” of anonymous types, the return type of GetActivitiesList() must be an IList.
 
That shrinks down my ActionResult to a single call.
 

try

 {

     return Json(_activityRepository.GetActivitiesList());

 }

 catch (Exception ex)

 {

     return Json(ex.Message);

 }

 
That works… and will work for now.  Though, I’ve marked it as a HACK in my code.  Why?  I’m honestly not sure yet.  Just a feeling.

Html.Grid Rendering as Plain Text?

September 23, 2009 1 comment

Notice: Stupid, stupid moment described ahead.  Proceed with caution.

I spent a good half hour trying to figure out why my MVCContrib Html.Grid<T> wasn’t rendering.  It wasn’t throwing an error, it was simply returning the HTML code as Plain Text.

  • The AutoMapper code looked good,
  • The Html.Grid<T> code looked good (it’d be templated off another page anyway and that page was working),
  • The view model code looked good.

So why was I being greeted with garble junk?

${Html.Grid(Model.Details) .Attributes(Id => “RoutineDetails”) .Columns(column => { column.For(c => this.Button(“EditDetail”).Value(“Edit”).Id(string.Format(“edit_{0}”, c.Id))).DoNotEncode(); column.For(c => c.Activity.Target.Name).Named(“Target Area”); column.For(c => c.Activity.Name).Named(“Activity”); column.For(c => c.Sets); column.For(c => c.Weight); column.For(c => c.Repetitions); column.For(c => c.Duration); })}

Html.Grid that is not… well, at least not properly.

Encoding issue? Maybe. Data issue? Perhaps.

No, the issue was typing too quick and not paying attention.

public ActionResult New()

 {

     var viewModel = BuildRoutineNewViewModel(new Routine());

     return View();

 }

Yeah, that’s the problem… right there.  I’d forgotten to pass the view model into the View.  Apparently the Html.Grid<T> helper simply panics if the model you’re reading from is empty or null—rather than throwing an error.

Oddly enough, this is one of those times I’d wish the screen would have lit up red.  Lessons learned.

Follow

Get every new post delivered to your Inbox.