try-catch-FAIL

Failure is inevitable

NAVIGATION - SEARCH

Turn an Array into Proper-English with an AngularJS Filter

I needed a way to display a nicely-readable list of strings for an app I'm working on. And by that, I mean that I wanted to display, "Mary, John, and Mark" instead of "Mary, John, Mark". A simple ngRepeat would have been too complex for this, so, filters to the rescue!

Let's back up a step and talk about why... Why the heck would I want to invest energy in changing from this:

"Mary, John, Mark"

to this:

"Mary, John, and Mark"

The difference is subtle, but I think touches like that go a long way towards improving the overall UX of an app, especially when your target users aren't the technical type to begin with.

A Naive Solution

I started off thinking, "Well, I could just use an ngRepeat or something...", but I quickly abandoned that idea. It would have looked something like this:

<p>
    <span ng-repeat="person in people">{{person}}{{$index < (people.length-1) ? ',' : ''}}</span>
</p>

It's already unreable and I didn't actually get my 'and' in there!

A Better Solution

So, ngRepeat is off the table. Instead, I decided to go with a filter.

(function (undefined) {

    angular.module('app').filter('sentenceJoin', () => sentenceJoin);

    function sentenceJoin(value, finalSeparator) {
        //If we didn't get an array, just return the value.
        if (!value || !value.constructor === Array) return value;
        
        //If there's a single item, just return it...
        if (value.length === 1) return value[0];

        //If there's only two, we don't need a comma...
        if (value.length === 2) return `${value[0]} ${finalSeparator} ${value[1]}`;

        //Otherwise, join it up, throw the final separator in place at the end! 
        return `${value.slice(0, value.length - 1).join(', ')}, ${finalSeparator} ${value.slice(-1)}`;
    }
    
})();

Now my solution looks like this:

<p>
    {{people | sentenceJoin:'and'}}
</p>

Assuming people=['Mary','John','Mark'], this gives me <p>Mary, John, and Mark</p>.

And if I only have two people, people=['Mary','John'], I get back <p>Mary and John</p>.

Again, this isn't a HUGE change from what I could have gotten with just a simple Array.join call, but it's the little things that make the difference between a good UX and a great one.

About Matt Honeycutt...

Matt Honeycutt is a software architect specializing in ASP.NET web applications, particularly ASP.NET MVC. He has over a decade of experience in building (and testing!) web applications. He’s an avid practitioner of Test-Driven Development, creating both the SpecsFor and SpecsFor.Mvc frameworks.

He's also an author for Pluralsight, where he publishes courses on everything from web applications to testing!

blog comments powered by Disqus