• Broadcasting AngularJS events from vanilla JavaScript

    Broadcasting AngularJS events from vanilla JavaScript

    In this short post I’ll show how to invoke AngularJS from plain JavaScript. Why would you want to do this? Well, in certain edge cases you might need to catch events in plain JS but still want to handle them back inside your Angular app. For example on an SVG element mouse event..

    Say you have an Angular controller named SomeCtrl and that’s where you want to handle the event. You’ll need an element you’ll be able to target either by an id or by a class, and it needs to be scoped with a controller like this:

    Next, say you have something like onmouseover=”onMouseOver()” on one of your HTML/SVG elements:

    You’ll need to add a $scope.$on listener for the “mouse-over-event” event inside your SomeCtrl controller. Your Angular app will catch the broadcast, you’ll be back inside the Angular scope and digest loop and you’ll be able to handle the event further from there.

    That’s it!

  • Detecting no-Internet / user-offline in Angular

    Detecting no-Internet / user-offline in Angular

    Sometimes, a user might find himself disconnected from the Internet after he already got to your page. Given the nature of SPA apps, this situation might not be very obvious to the user at first and he might end up thinking that the “site doesn’t work”. If the user goes offline after he already landed on your AngularJS site, the back-end API’s won’t be accessible any more but all the client-side stuff will still remain loaded if the user does not refresh the page. The problem is – because the page is still visible and some events still respond to his input, he might not notice (or even understand) what actually happened.

    This may result with a call from your client. :) To prevent having to explain the whole situation, it might be easier to handle this situation in advance. For example, you could detect if the user is offline and then redirect him to a “warning” or an “error” page (you might want to precache the error page template upon page load).

    There is a very simple way in AngularJS to detect whether the user is disconnected from the Internet or not. Simply use/attach the following http-request-interceptor to your app.

  • Pre-caching HTML templates with AngularJS ui-router directive

    Pre-caching HTML templates with AngularJS ui-router directive

    Unless you’re using gulp-angular-templatecache (which you probably should) to bundle your HTML templates into an Angular Javascript module, you might in some cases want to pre-cache certain HTML files. For example if you have a specific “error page” HTML template used to display a specific error message telling the user he lost his Internet connection. If you don’t pre-cache such a template, your Angular app won’t be able to fetch it from the server (because the browser is obviously off-line) and as a consequence it will be unable to display this important message.

    If you’re using ui-router, there is an easy way to pull the template from the server before it’s even used. I like having an abstract root state which I setup in my app.config() (inside app.js) to kind of abstract my base layout. Views from this root state can then be overridden by any child state which is very handy for having a few different types of layouts. For example, some with a sidebar, some without, etc.

    The cool thing about the abstract root state is that it will fetch all templates specified inside its views property even if they’re not used right away and it will put them into Angular’s template cache. The next time any of our child ui-router states requires one of these cached templates, it won’t make a request against the server but it will simply reuse the cached template.

    You can use this simple trick to if needed cache any other templates as well. Obviously don’t overdo it because you want to make the smallest amount of initial requests you can to speed-up the loading time. Or even better – use angular-templatecache, it’s wonderful. :)

    Cheers!

  • Downloading/streaming Azure Storage private container blobs to AngularJS through .net WebAPI

    Downloading/streaming Azure Storage private container blobs to AngularJS through .net WebAPI

    When our Azure storage contains files that are meant to be publically accessible, it’s pretty trivial to deliver them to the end-user. We can either embed such items (e.g. images) or simply add links which point to them (e.g. pdfs) because Azure provides direct links to them. But what happens when these files contain sensitive data that is not meant for just anyone? Perhaps some kind of reports?

    Well, it gets a bit more complicated.. Since these files don’t have publically accessible URI’s any more, there are several steps which we need to go through:

    • Authenticate against Azure using SDK
    • Load the file into MemoryStream
    • Deliver the stream to the client (browser)
    • Convert the byte array into an actual file on the client-side and simulate “downloading”

    Since we’ll need more than just the MemoryStream, we’ll wrap it together with the file metadata into a model object.

    We will use AzureProvider class to authenticate against Azure, download the file from Azure and to create the model object.

    Our actual controller will inherit from this BaseApi class which contains a custom IHttpActionResult method which we can name AzureBlobOk. This is something pretty reusable so it’s good to have it at hand in your base class. What it does is it sets up all the content headers and it attaches the stream as the response content payload . It also returns HTTP status 200 which means OK – everything went fine.

    The actual controller is pretty simple..

    On the client side, we’ll need the following service to actually convert the byte array that we got from the API into something meaningful. I tried various approaches, but in the end decided to use FileSaver.js which “implements the HTML5 W3C saveAs() FileSaver interface in browsers that do not natively support it”. What it will do is turn the byte array into an actual file and prompt the user to download it.

    This service can easily be consumed by injecting it into your AngularJS controllers and calling the .getBlob() function which will do all the heavy lifting for you.

    Hope this helped, enjoy! :)

  • Handling WebAPI exceptions with Angular http interceptor

    Handling WebAPI exceptions with Angular http interceptor

    It’s good to return meaningful HTTP status codes upon server exceptions. Whether it be invalid model state, conflict upon trying to create/update an object in the database, unauthorized access or something else it adds additional value and sends a message – one that’s different from generic 400’s or 500’s. These messages can then be used to take certain kinds of actions on the client side based on what happened.

    For example you could register a custom ApplicationExceptionHandler.cs inside your WebApiConfig.cs which would then be able to catch and handle any kind of exception thrown by lower server layers (such as business layer or the DB/ORM layer):

    You need to register ApplicationExceptionHandler in WebApiConfig.cs like this:

    You can also use something like ValidationFilter to take care of invalid model states in an easy way (by replying with a 422). After you have all your desired/needed exception handlers in place, it’s time to setup the client side. You can easily intercept every HTTP request and act upon responses from the server with an http request interceptor that looks like this:

    Now you have a centralized way to handle all kinds of WebAPI errors. Simply build upon this infrastructure and add whatever else you might need. In one of the future posts I’ll explain how to create basic html input element directives (for text, textarea, number, datetime and similar fields) which also seamlessly take care of modelState error messages by presenting them to the user just below the input element.

  • Invalidating Angular template cache with .net BundleConfig.cs

    Invalidating Angular template cache with .net BundleConfig.cs

    You most probably had the problem with old Angular templates not clearing themselves up from the browser cache in production which can cause various problems. If you’re using gulp, you can use something like gulp-angular-templatecache to tackle this problem (which would also be a preferred way of doing this) but if you’re using .net’s BundleConfig.cs to bundle your scripts, you’ll have to add a bit of code to your app.

    Say your app bundle section inside BundleConfig.cs looked something like this:

    Then you would include that inside your index.cshtml (or some other Razor template) like this:

    And this is how the generated HTML script include tag would look in production:

    <script src=”/bundles/my-app?v=6XgTJerMdBNglpDE1l_sgb9JgKJDXS35tee8zasXvLk1″></script>

    What changes upon every deploy is the “v” (version) hash at the end of bundle link. We can leverage that to keep track of the current version by extracting and storing that value within a cookie. Then on a full page reload (F5) if the version hash changed – we can simply clear the template cache and let the user continue using the app. The app will then have to re-cache all the templates once they are requested by the router or a directive.

    That piece of logic can be stored inside app.js on MyApp.run(). Here is how I did it:

    NOTE: I use lodash in every project so if you’re not using it, you might have to write your own code to replace _.find() and _.contains()

Back to top