Creating and using your own AngularJS filters

I have been working on the client-side portion of a rather complex feature and I found myself needing to trim certain things off a string when binding it in my AngularJS code. This sounded like a perfect job for a filter. For those familiar with XAML development on .NET-related platforms like WPF, Silverlight and WinRT, a filter in Angular is similar to a ValueConverter. The set of built in filters for Angular is pretty limited and did not support my desired functionality, so I decided to write new filter of my own called trim. I even wrote some simple testing for it, just to make sure it works.

Testing

For the sake of argument, let's presume I followed TDD or BDD principles and wrote my test spec up front. I used jasmine to describe each of the behaviours I wanted1.

describe('trim filter tests', function () {
	beforeEach(module('awesome'));

	it('should trim whitespace', inject(function (trimFilter) {
		expect(trimFilter(' string with whitespace ')).toBe('string with whitespace');
	}));
		
	it('should trim given token', inject(function (trimFilter) {
		expect(trimFilter('stringtoken', 'token')).toBe('string');
	}));
		
	it('should trim token and remaining whitespace', inject(function (trimFilter) {
		expect(trimFilter(' string token ', 'token')).toBe('string');
	}));
});

An important point to note here is that for your filter to be injected, you have to append the word Filter onto the end. So if your filter is called bob, your test should have bobFilter as its injected parameter.

Implementing the Filter

With the test spec written, I could implement the filter. Like many things in Angular that aren't directives, filters are pretty easy to write. They are a specialization of a factory, returning a function that takes an input and some arbitrary parameters, and returning the filter output.

You add a filter to a module using the filter method. Below is the skeleton for my filter, trim.

var myModule = angular.module('awesome');

myModule.filter( 'trim', function() {
    return function (input, tokenToTrim) {
        var output = input;
        // Do stuff and return the result
        return output;
    };
});

Here I have created a module called awesome and then added a new filter called trim. My filter takes the input and a token that is to be trimmed from the input. However, currently, the filter does nothing with that token; it just returns the input. We can use this filter in an Angular binding as below.

<p style'font-style:italic'>Add More {{someValue | trim:'Awesome'}} Awesome</p>

You can see that I am applying the trim filter and passing the token, "Awesome". If someValue was "Awesome", this would output:

Add More Awesome Awesome

You can see that "Awesome" was not trimmed because we didn't actually implement the filter yet. Here is the implementation.

myModule.filter('trim', function () {
	return function (input, token) {
		var output = input.trim();

		if (token && output.substr(output.length - token.length) === token) {
			output = output.substr(0, output.length - token.length).trim();
		}
		return output;
	};
});

This takes the input and removes any extra spaces from the start and end. If we have a token and the trimmed input value ends with the token value, we take the token off the end, trim and trailing space and return that value. Our binding now gives us:

Add More Awesome

Perfect.

  1. Try not to get hung up on the quality of my tests, I know you are in awe []

Downloading images on Windows Phone 7

I've been spending some time recently working on my very first Windows Phone application. As part of the application, I decided to use the WebBrowser control to display content. This worked well until I had image links. I had read that for them to show, they had to be in isolated storage and so did the HTML1, so I spent some time coding that and it appeared to work. However, I didn't want all the images to be a part of my app, I wanted to download them on demand and then store them for later.

I wrote some great code based on the many examples out there that use BitmapImage, HttpWebRequest or WebClient to grab the images, but to no avail. No amount of searching seemed to solve my problem. Every single time I would get a WebException telling me the resource was "Not Found". Not one Bing, Google or divining rod search got me an answer and I was near ready to give up. The Internet and my own abilities had failed me.

Just as I was about to go to bed I had an epiphany; CAPABILITIES! I quickly opened my WMAppManifest.xml and checked the information on MSDN to confirm my suspicion. I had not added the ID_CAP_NETWORKING capability which meant my app was not allowed to download data. A quick change and suddenly, everything worked.

I am amazed that not one search provided me with this answer. Every search around image problems for Windows Phone showed up incorrect advice about ClientAccessPolicy.xml (not necessary for Silverlight on Windows Phone) or terrible code examples that completely misuse disposable items and extension methods. In a future post, I'd like to expand on this topic to provide a more rounded set of samples for downloading images, but for now, I just want to get something out there that helps someone else when they discover this problem.

I highly recommend removing all capabilities from your manifest and then adding them back in as you discover which ones you need – after all, an app that wants less access is more desirable (at least for me, anyway) – however, I now realise that the act of discovering what capabilities you should have can be a bit of a pain in some circumstances.

  1. This advice is not entirely true. If you want your HTML to reference images that are in isolated storage, your HTML also needs to be loaded from isolated storage. If the images are online somewhere, your HTML can come from anywhere, just make sure you've added the ID_CAP_NETWORKING capability! []

Crash handling in Silverlight (Part Two)

This post is the second part of a two part series.

Adding a little polish

In part one of this series we learned about the basic out-of-the-box crash handling that a new Silverlight project provides for both in- and out-of-browser applications, we learned how we can catch unhandled exceptions inside our application or let them escape into the browser to be handled by JavaScript (or a bit of both) and we learned that we are at the mercy of the HTML bridge.

What we had was far from fancy; the user would end up with a potentially broken Silverlight application or a blank screen and only some cryptic text in the JavaScript console to explain. This is not how we make friends, but now that we have a foundation, we can look at how to enhance the experience for our quality departments, ourselves and the poor souls that must suffer for our mistakes, our users. However, some simple modifications to our error handler can move the cryptic text out of the console into the page. We can even add some pizzazz and remove most of the cryptic text too. So let's take what we were left with at the end of part one and add a little polish.

In the following example, I've constructed a simple page that gives the user some information and provides a mailto link for sending the details to our QA department. When a crash occurs, the Silverlight application is hidden and the error page is displayed, customized to the specific error code1 and information.

function onSilverlightError(sender, args) {
    var errorType = args.ErrorType;
    var iErrorCode = args.ErrorCode;

    var emailMessage = "Dear Support,%0A%0A" +
        "Your application crashed.%0A%0A" +
        "Honestly, I only:%0A" +
        " ADD SOME DETAIL OF WHAT HAPPENED HERE%0A%0A" +
        "If you could fix this, that would be super awesome.%0A%0A" +
        "Thanks,%0A" +
        "A Very Important User%0A%0A~~~~~~~~%0A%0A";

    if (sender != null && sender != 0) {
        emailMessage += "Source: " + sender.getHost().Source + "%0A";
    }
    emailMessage += "Code: " + iErrorCode + "%0A";
    emailMessage += "Category: " + errorType + "%0A";
    emailMessage += "Message: " + args.ErrorMessage + "%0A";

    if (errorType == "ParserError") {
        emailMessage += "File: " + args.xamlFile + "%0A";
        emailMessage += "Line: " + args.lineNumber + "%0A";
        emailMessage += "Position: " + args.charPosition + "%0A";
    }
    else if (errorType == "RuntimeError") {
        if (args.lineNumber != 0) {
            emailMessage += "Line: " + args.lineNumber + "%0A";
            emailMessage += "Position: " + args.charPosition + "%0A";
        }
        emailMessage += "Method Name: " + args.methodName + "%0A";
    }

    var errorScreen = "<h1>Hello World!</h1>"
        + "<p>Sorry, but our application appears to have left the building.</p>"
        + "<p>Please <a href=\"mailto:quality@example.com\?subject=Incident Report&body="
        + emailMessage
        + "\">click here</a> and send us an e-mail.</p>";
    document.getElementById("silverlightControlHost").style.display = "none";
    var errorDiv = document.getElementById("errorLocation");
    errorDiv.innerHTML = errorScreen;
    errorDiv.style.display = "block";
}

Now, I understand, this is not the most elegant JavaScript in the world, but it works. Here is what your user sees…

Example of what a user will see when the application crashes
Example of what a user will see when the application crashes

…and if the user clicks our mailto link, they'll get something like this…

Example of the auto-generated e-mail incident report
Example of the auto-generated e-mail incident report

The example could be expanded to add additional information such as the URL of the application, the version of Silverlight and the user agent string by just modifying the JavaScript to include that information2. You could even show the same information on the HTML page that you include in the e-mail (in fact, you can go even further than that, just use your imagination…or read on for some suggestions). And yes, a little CSS would help, but I never promised it would be pretty—pretty can come later; I'm aiming for functional and as functional goes for showing that something is non-functional, this is good enough.

A bridge too far

Of course, as we have access to all the wonders of HTML and JavaScript, we could do so much more. For example, we could play a video to entertain the user while we call a web service that sends our error report automatically to our servers and tweets an apology (it's the personal touches that count). However, it doesn't matter how fancy and special we make the crash experience, it is all for nought once the user installs and uses our application out-of-browser or the HTML bridge is disabled. So, what do we do?

Out of the browser and into the app

The simplest way I have found to handle crash reporting in an out-of-browser application (or an application that lacks the HTML bridge) is to throw up a ChildWindow containing the details of the crash and provide no discernible means to dismiss it, thus disabling your application from further use without closing the application. This relies on the Silverlight runtime remaining intact even though your application suffered a problem; however, from my experience, crashes that take out the runtime are rare, especially in applications that have been tested and have well-formed, correct XAML.

Of course, if the runtime is still working, why stop at a ChildWindow? If you have access to the Silverlight runtime, you could do more like call a web service call or use some trusted API3 or COM4 interface. Whatever you try, exercise caution as you don't want your crash handling to crash as well. Keep it simple and it will serve you well.

Conclusions

Whichever route you choose, you should work hard to cater for all the scenarios that might be encountered, that way you will provide the support your user deserves. When deciding on your crash reporting strategy, always consider:

  • What level of network connectivity might be available?
  • Will the application be in- or out-of-browser? Do you support both?
  • Will the application be trusted and therefore have access to COM or Windows APIs?5
  • What Silverlight runtime(s) will you want to support?
  1. If you were paying attention there, you may have noticed that I mentioned the error code. There are many error codes that can be reported by Silverlight. You can use the error code to tailor your report or even consider not reporting a crash at all, but that depends on just how badly your application will react to the error. []
  2. Getting the User Agent string or the site URL are relatively simple, especially when compared with retrieving the Silverlight runtime version from within JavaScript. Thankfully, this was solved already, just visit this blog for details. []
  3. Silveright 5 []
  4. Silverlight 4 and up []
  5. Starting in Silverlight 5, both in- and out-of-browser trusted applications are supported. Earlier versions only support trusted applications when out-of-browser. []

Crash handling in Silverlight (Part One)

This post is the first part of a two part series.

I love working with Silverlight but once in a while I get it wrong and I, or worse, a user experiences a crash incident. I believe it is important for developers to acknowledge that incidents will occur and to include incident handling and reporting as first class citizens in the software we write. It benefits both us and our users by providing both a graceful degradation of our application and a source of feedback regarding application stability and bugs.

In this and subsequent posts, I want to take a look at the functionality a new Silverlight project includes for handling and reporting incidents, and then build upon it to give us some top notch error handling in our Silverlight applications.

So, let's start with the basics1

Create a new Silverlight application (including a companion ASP.NET web application or website) and you'll get two flavours of error handling: the first reports errors when you're not debugging your application and the second reports errors when you are2. When there is no debugger attached, errors are reported to the DOM via the HTML bridge. This all happens in App.xaml.cs via an event handler for the Application.UnhandledException event, which is subscribed in the class constructor. The event handler checks whether the debugger is attached and if it is not, it sends the error to the DOM via the cunningly-named ReportErrorToDOM method. The comments in Application_UnhandledException explain what is happening. Also, note that the event is being marked as handled, meaning our application won't stop running just because of this pesky exception.

private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
    // If the app is running outside of the debugger then report the exception using
    // the browser's exception mechanism. On IE this will display it a yellow alert
    // icon in the status bar and Firefox will display a script error.
    if (!System.Diagnostics.Debugger.IsAttached)
    {
        // NOTE: This will allow the application to continue running after an exception has been thrown
        // but not handled.
        // For production applications this error handling should be replaced with something that will
        // report the error to the website and stop the application.
        e.Handled = true;
        Deployment.Current.Dispatcher.BeginInvoke(delegate
        {
            ReportErrorToDOM(e);
        });
    }
}

And a quick look at ReportErrorToDOM shows us the HTML bridge is being used to evaluate some JavaScript that will throw an exception inside the hosting browser.

private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
    try
    {
        string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
        errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n";, @"\n");

        System.Windows.Browser.HtmlPage.Window.Eval(
            "throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
    }
    catch (Exception)
    {
    }
}

If you try this and you're using a recent browser, it's very likely that you won't even notice anything happened. I put a button on my vanilla application and tied that to a click-event handler that throws an InvalidOperationException exception. Clicking it in IE9 gave me nothing until I pressed F12, viewed the Console in the developer tools and tried again. In some older browsers, a dialog box may appear indicating a scripting error.

Console in IE9 after a crash using basic Silverlight exception handling
Console in IE9 after a crash using basic Silverlight exception handling

I'll leave it as an exercise for you to go and see exactly what this looks like in your browser of choice, but I think we can all agree that with error handling like this our users must surely feel a warm fuzzy glow (especially with our hidden, cryptic error message and an application that continues running, unfettered by the potentially fatal bug lurking within). In fact, if the HTML bridge is disabled3, there isn't even a cryptic error message!

However, you'll be pleased to read that things are almost ever so very slightly better different when we have the debugger attached.

Attaching the debugger

The exception handler we just looked at only reports the error to the DOM when the debugger is not attached (and the HTML bridge is enabled). When the debugger is attached, the handler does nothing at all and the exception goes unhandled by our application. So what happens next?

Well, when an unhandled exception leaves our application, the Silverlight host looks for a JavaScript method assigned to the onError parameter. If there is such a method, it calls that and stops the application. The default handler is defined for us in the auto-generated HTML and ASPX. You can see its assignment in the default HTML and ASPX pages generated for us when we created our Silverlight application.

<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
    <param name="source" value="ClientBin/AgIncidentReporting.xap"/>
    <param name="onError" value="onSilverlightError" />
    <param name="background" value="white" />
    <param name="minRuntimeVersion" value="4.0.50826.0" />
    <param name="autoUpgrade" value="true" />
    <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration:none">
        <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight" style="border-style:none"/>
    </a>
</object>

The default JavaScript handler generates an error similar to the one we get without the debugger, but with a few extra details4. Unfortunately, just like when the debugger isn't attached, disabling the HTML bridge (or running out-of-browser) also disables the error being reported.

Console in IE9 after a crash using basic Silverlight exception handling with debugger attached
Console in IE9 after a crash using basic Silverlight exception handling with debugger attached

The story so far…

In this introduction to Silverlight incident handling we have seen that, out of the box, we get some basic reporting that in a release scenario, will allow the application to continue running and will output a stack trace in the console5 but, when debugging, will stop the application and output a stack trace plus the added bonus of some extra details5.

I think you will agree, this is not a first class system for handling errors. Of course, all is not lost and in the next post we will look at how we can expand this error handling to be more helpful to both us and our users, perhaps even coping without the HTML bridge. That said, if this is all you use, I recommend deleting the code from App.xaml.cs so that the "debugger attached" style handling is used for all scenarios6. At least that way, when your application crashes, the user won't be able to continue using the application in blissful ignorance of whatever dangers lurk beneath.

  1. More detailed information on error handling in Silverlight, can be found here. []
  2. I am using Visual Studio 2010 Professional SP1 with the Silverlight 4 SDK. All line numbers refer to a vanilla Silverlight project created using New Project in the File menu. []
  3. You can disable the HTML bridge by adding <param name="enableHtmlAccess" value="false" /> to your Silverlight object declaration or by running your application out-of-browser. []
  4. The Category value is only available if the development runtime is installed, but the Code value is provided with all runtimes. It indicates the type of error, which can be looked up here. []
  5. If we're running in a browser with the HTML bridge enabled. [] []
  6. Please don't actually use this as your error handling. Although it is in the most part, better for the user, your application will appear to crash a little more often as the onError handler gets called for more than just unhandled exceptions. []