flashular icon indicating copy to clipboard operation
flashular copied to clipboard

A Rails-inspired flash service for AngularJS. Anything you place in the flash is exposed to the very next route and then cleared out. Also includes a Bootstrap-compatible directive for displaying flas...

flashular Bower version Build Status devDependency Status

A simple flash service for AngularJS that provides you with the means to pass temporary data between routes (or "states", if using UI Router terminology). Anything you place in the flash is exposed to the very next route and then immediately cleared out, making it somewhat similar to the Rails flash. Also comes with a Twitter Bootstrap-compatible directive for displaying flash alerts.

Installation

You can manually add the flashular.js file to your AngularJS application, or install it with Bower:

$ bower install flashular

After that, just add Flashular to any Angular module's dependency list:

angular.module("app", ["flashular"])

Service

Flashular provides a flash service that allows you to temporarily store values of any type (e.g. strings, arrays, objects, etc.) so that they are available for retrieval when the $location changes. Values are only stored in the flash for a maximum of one $location change before being cleared out.

To use the flash service, simply inject it as a dependency in your Angular controller:

.controller("SignInCtrl", function(flash) { ... })

The injected flash service is simply an object that stores a bunch of key-value pairs intended for the next $location. It exposes the following functions you can call to manipulate and query the stored data:

flash.get(key) // Returns the value stored in the flash for the specified key.
flash.set(key, value) // Stores a value in the flash with the specified key.
flash.has(key) // Returns a boolean indicating whether a value is stored in the flash for the specified key.
flash.remove(key) // Removes the value stored in the flash with the specified key.
flash.clear() // Removes all key-value pairs in the flash.
flash.isEmpty() // Returns a boolean indicating whether any key-value pairs are stored in the flash.

It also has two properties:

flash.data // All key-value pairs as stored in their "raw" form. Try not to touch this.
flash.now // The flash object intended for the current $location. Has all the same methods above.

As can be seen, the flash stores data for the next $location, and its now property is itself a flash that contains the data stored for the current $location. When the $location changes, the "next" flash becomes the "current" flash. Here's a code example to demonstrate how it all works:

// Store a value for the next $location.
flash.set("username", "John Smith")
flash.has("username") // Should return true.
flash.now.has("username") // Should return false.
flash.get("username") // Should return "John Smith".

// --- $location change occurs.

// Get the value stored for the current $location.
flash.has("username") // Should return false.
flash.now.has("username") // Should return true.
flash.now.get("username") // Should return "John Smith".

Directive

Flashular also provides a flashAlerts directive that allows you to easily display "alerts" in your HTML templates. Anything you store in the flash with a key of info, success, warning, or danger will automatically be rendered as an alert wherever you include this directive in your templates. Furthermore, the HTML outputted by this directive is completely compatible with Twitter Bootstrap (and doesn't require UI Bootstrap either!).

Adding the flashAlerts directive to a template can be done like so:

<flash-alerts closeable="true"></flash-alerts>

It should be mentioned that this directive utilizes the flash for the current $location i.e. flash.now. So if you store alerts in the flash for the next $location, they will only render once the $location actually changes. If you want to immediately display an alert without waiting for the $location to change, then just add values to flash.now, of course.

Need to do some pre-processing of your alerts before they are rendered? Just add a preProcess attribute, which should specify a function that has a single parameter (the alert stored in the flash, which can be any type) and returns the "processed" alert (which should be something renderable, like a string):

<flash-alerts pre-process="processFlashAlert"></flash-alerts>

How might this be useful? Well, flash alerts are definitely something you want to localize, for example. But a lot of i18n libraries out there tend to load their translation dictionaries asynchronously. So what if you want to store a translated alert string in the flash, but i18n hasn't finished loading yet? You can't do it. Or can you?

Flashular automatically detects changes to the return value of your preProcess function and re-renders alerts as needed. So if your i18n library returns null or an empty string if you try to use it before it has finished loading, and a translated string once it has loaded, then it's pretty obvious what you should do - perform the translation inside your preProcess function!

Still not clear? Below is an example:

// Define a translation in your i18n dictionary.
{"key": "SIGN_IN_SUCCESS", "value": "You signed in successfully. Welcome back, %s!"}
// Store the i18n dictionary key in the flash along with any strings to substitute.
flash.set("success", ["SIGN_IN_SUCCESS", username]);
// Perform translations and string substituting in the preProcess function.
$rootScope.processFlashAlert = (alert) => {
  let [message, ...args] = alert;
  return stringUtils.format(i18n.translate(message), ...args);
};

Alert example

Contributing

All contributions are welcome.

Execute npm install to sort out your development dependencies, npm start to auto-build Flashular while you work, and npm test to run the Protractor e2e test suite.

Make your changes to flashular.coffee. Don't commit the transpiled flashular.js and flashular.min.js scripts - I always re-generate those myself prior to releasing a new version.

Development Roadmap

Some things to look at doing:

  • A small sample/demo application on GitHub Pages.
  • Replicate more functionality of the Rails flash.
  • Make the flashAlerts directive more compatible with other front-end frameworks e.g. Foundation.