Angular directive for loading JSON data embedded in the HTML

Angular directive for loading JSON data embedded in the HTML

I’ve used AngularJS in quite a few projects by now, but mostly as a sort of replacement for jQuery and not for doing SPAs – Single Page Applications.

Being an ASP.NET/C# guy I’m mostly working with either Webforms or MVC. When returning af view/HTML I often find myself wanting to initialize the Angular controller with some data, e.g. an array of items or som configuration data.

To do that I can either use ng-init or load it asynchronously through a web service. ng-init doesn’t feel right to me. It’s also a bit cumbersome and can be a bit difficult to debug the data. Loading it asynchronously requires me to create a web service, add an endpoint to it etc. for each new view, which just feels like a lot of work for basically nothing and you also add another async request to your page load.

So I decided to create a simple directive that could load JSON embedded somewhere in the HTML and store it in a property on your controller or pass the data to a callback function when loaded.

Installation

You can install the directive through bower or npm or just copy it directly from the Github repository and use it in your solution.

Bower: bower install angular-json-data

Node: npm install angular-json-data

Usage

To start using the directive you need to include json-data as a dependency for your app:

// Add 'json-data' as a dependency for your app
var app = angular.module("MyApp", ["json-data"]);

Below are some examples on how to then use the directive.

<!-- Use the 'model' attribute to store the data in a property on your controller -->
<json-data model="vm.movies">
    [
        { "title": "Warcraft: The Beginning", year: 2016 },
        { "title": "Star Trek: Beyond", year: 2016 }
    ]
</json-data>

You can use the callback attribute to be notified when the directive have been initialized and the data loaded.

The data variable will be substituted with the loaded data, but you don’t have to include it.

<!-- Will call vm.onMovieLoaded() with the JSON object when initialized -->
<json-data callback="vm.onMovieLoaded(data)">
    {
        "title": "Warcraft: The Beginning",
        "year": 2016,
        "imdbScore": 7.5,
        "cast": [
            "Travis Fimmel",
            "Paula Patton",
            "Ben Foster",
            "Dominic Cooper"
        ],
        "director": "Duncan Jones"
    }
</json-data>

You can also combine the two if you want to.

<json-data model="vm.movies" callback="vm.onMoviesLoaded()">
    <!-- ... -->
</json-data>

All valid JSON can be used – objects, arrays and simple types.

<!-- You can store objects, arrays or simple types - all valid JSON can be used -->
<json-data model="vm.count">5</json-data>
<json-data model="vm.userName">"Krusen"</json-data>
<json-data model="vm.isAdmin">true</json-data>

<!-- 'when-all-initialized' attribute will be called when all surrounded json-data directives has been initialied -->
<json-data when-all-initialized="vm.onAllLoaded()">
    <json-data>
        <!-- ... -->
    </json-data>
    <json-data>
        <!-- ... -->
    </json-data>
</json-data>

By default the directive/element will be removed from the DOM after it has been initialized. If you do not want this behavior you can add a keep-element attribute.

<!-- This will stay in the DOM after being initialized -->
<json-data model="vm.data" keep-element>
    <!-- ... -->
</json-data>