Best Parts of Aurelia Part 1 – Composing custom elements / templates

In a renewal of a previous set of posts that I did around Durandal.js, I wanted to start a new series on Aurelia, the successor to Durandal.js and Caliburn.Micro.  Aurelia is an awesome collection of libraries that make up an amazing framework that is focused on future specs of the JavaScript language while still supporting a large set of current browsers.

Code

For this quick highlight of the features we will use this repo, which is a basic layout out with multiple columns which contain some widgets –

https://github.com/PWKad/aurelia-layout

It is a basic fork of the Aurelia skeleton-navigation. For any questions please visit the official gitter –

https://gitter.im/Aurelia/Discuss

Composing templates and custom elements

What’s the difference between using the compose element vs a custom elements? In what situations do we use each of them with Aurelia? How does it fit into the web components spec?

Compose:

  1. Can be used to dynamically compose templates (not forced to define the template type)
  2. Can use same view model but different view for each item in an array
  3. You can separate your views and view models into the smallest bits of (re-usable) code needed.

Imagine you want to create between 1 and 3 number of columns that are in charge of their own visibility and data-binding.  Easy.  Using the compose element with a repeat.for binding.

<compose view-model="./column" model.bind="column" repeat.for="column of selectedColumns.columns"></compose>

In this case we are using the compose element to bind to a template where we can provide our own view-model, view, or model. Let’s dissect what we did above –

Set the view-model to ./column to let the compose custom element know that A view-model can be found in this same folder “./” named column.js “column”. The compose custom element will then look for a corresponding view to bind to, and locates in the same folder or by convention if we have one set.

What’s really cool is we could have bound the view-model to a property so if we were iterating over an array of columns in our parent view-model we could have set a different view-model / view pair based on some condition, such as ‘columns/green’ to indicate a column in good standing vs ‘columns/red’ to represent one in bad standing.

We bind the model to the column, which in this context is set to a column we defined in our repeat.for binding.

This means in the parent view-model (such as layout.js) we need to define a property called columns which is an array, such as –


export class Welcome{
	constructor(){
		this.columns = [{ name: 'column1' }, { name: 'column2' }];
	}
}

Custom element:

A custom element is basically a web component. It uses the future spec to create a view-model / view pair that is highly re-usable and componentized.

Now we need to create a column view template in the same folder. Let’s create a new .html file and wrap the .html in a template tag that let’s Aurelia know this is a template that we want to re-use.



  <div class="column">${column.name} if you lower-case it is ${column.lcName}.</div>


Next we create a view-model to pair up to it to allow handling any of this particular columns’ properties or methods. In this example we create an ES6 module but in our skeleton-navigation app Aurelia can convert this to your favorite module format (AMD, CommonJs, etc…)


export class Column {
  constructor () {
    this.column = { name: '', lcName: '' };
  }

  activate(col) {
    this.column.name = col.name;
    this.column.lcName = col.name.toLowerCase();
  }
}

Here we are defining an activate callback that the module loader will call when first activating the view-model and pass the column we bound the model to before in the parent. This was the compose binding before where we used model.bind in our view.

How does it work together?

In the case above the view model column.js and view column.html make up a custom element. We used the compose custom element to instantiate an instance of it to dynamically render it in the DOM.

What else could we do instead?

We could import it directly in the DOM –

  <import from='./column'></import>

And then use it as a custom element there directly –

<column model.bind="column"></column>

The difference here is we are forced to use the column view-model and view pair.

Wrap-up

What we went over –

1. Compose’ing custom elements allow a very dynamic way to create partials that truly separate out our code in to functional areas.

2. Custom elements are web components that need to be imported or composed to use.

3. The templating engine for Aurelia is truly amazing and built for the future, but designed for use now.

Advertisements

Building the first SPA JavaScript game using Breeze.js and Durandal.js

So in the wild everyone is teaching you how to build a new enterprise application using single page application (SPA) architecture and libraries like Breeze.js.  I am a huge proponent of Breeze.js and what it can do for your application, but that is a different subject.  What I wanted to do now was share a project I am working on / building for a game contest that interests me.

Richard Garriott, the creator of Ultima Online, posted this challenge for developers to re-create a 1977 game called DND1 that was originally written in BASIC for a TeleType machine.  I started to try to figure it out and somewhere along the lines realized this would be fun to do in a single page application to show how powerful things like Breeze.js and Durandal.js can be for any purpose.

Check out the github here – http://github.com/PWKad/dnd-sota

Check out the working version of the game here – http://dnd.sotaexchange.com/

Let me know what you think in the comments!

Why Ember.js matters for Web Development

Over the last two years I have converted from being solely a Microsoft-stack developer into using a mix of technologies.  I no longer shy away from tech just because I might need to switch over to my Linux distro to get it fired up.  I love to try out new things if for no other reason than just to see how easy it is to use and find out more about why people are adopting it.  I have gotten to where I prefer to use Sublime Text as my editor instead of Visual Studio.  I like the ease of development that Linux offers me on my dual boot Win 8 / Ubuntu system and how powerful the terminal can be.  I still prefer Windows for my every day computing, but I can understand the other side as well.

Sometimes it seems that people on the other side hate on Microsoft technology just because they are so open source.  It makes sense sometimes when they argue that Microsoft charges for everything where open source tech is generally free, but to call C# and .NET bad compared to PHP or Python development is mis-informed, but that’s another post entirely.  I bring this up because in my quest for the perfect client-side framework I have stumbled upon something that is so open-source and community driven yet is embodying that which I feel is the perfect framework.

Of course it sounds cliche to say the new tech I am adopting and learning is the next greatest thing, but the truth is it is amazing.  Say what you want about the .NET framework and ASP.NET MVC and how much overhead is provided that is not needed, but you can’t say that it’s hard to use or slow.  The overhead that is provided is there to make the technology easy to learn and use.  It’s so easy in fact that it conventionally provides controllers, views, and mark-up for said views to basically build an app from scratch without having to write any code at all.  For the purist who loves to build everything from scratch this can be a real pain, but for new developers and for a team of developers who need to share the code base and build a product together this is invaluable.  It offers the team a convention to follow to build something great.  Why does that matter?  Because Ember.js is the new ASP.NET MVC.

Ember took a long time to build.  I don’t need to give the history (you can Google that if you wish) but the fact is the core Ember team took a long time to get things right.  The early adopters spent countless hours building Ember apps only to have huge breaking changes come.  Features were deprecated to get things right.  I admire them but I am glad it wasn’t me that had to go through this growing phase.  I had applications that I had to build and I built them in a framework that I loved.  The problem was that the community for that framework never grew out of the small niche of developers who realized the power and simplicity of it.  I plan to write another post on the topic, but the reality is if you want good quality dev’s you have to use technology that excites and draws good talent.

So why am I writing this post?  After spending three long weeks of researching Ember.js and trying to understand what problems it solves I had my aha moment – the answer was always there right in front of my face but it was so simple it was hard to comprehend.  Ember provides everything by convention.  If you don’t build controllers, it builds them for you.  Want to change the model from a single item to a collection?  No problem, just do it.  Ember is so opinionated about the future of the web it doesn’t wait for someone to tell it how to build it – it does it for them.

In a pure Ember application everything can be broken down to routes and resources, and resources and routes.  It’s so simple that the first time you see it that it is hard to fathom that a web application can be reduce to that level of simplicity.  Web Components can be delivered in many different ways.  Views can be rendered or created as partials.  Any way you spin it it’s already defined on how it should work and what Ember will do to provide it to you.

Ok, Ember.js is awesome, why should my team adopt it?

One of the biggest complaints about Single Page Application frameworks such as Angular, Backbone, Durandal, and the like are that it’s hard to scale.  It’s not hard for a developer to scale the application if they know what they are doing, but when that developer leaves the company it’s hard to scale the application to other developers.  Instead of spending the necessary time to learn the technology and scale it most developers see working code and are afraid to hack at it.  Ember provides conventions that are easy to follow and therefore it’s easy to look at another developers code and understand what it is doing.  This makes building an application that can be shared between many developers easy.  Being that Ember promotes code organization and the separation of concerns so well it is no surprise that the application is easier to break out when it grows.  The main problem that I have so far is that Ember-Data tries to tackle more than it should – which is why I hope to soon finish building out a Breeze plug-in to use with Ember and provide rich queryable data.

In a time when everyone talks about Angular just because it’s the ‘next big thing (from Google)’ it’s really refreshing to see something that is both more opinionated and easier for developers to understand.

Please feel free to leave comments on why I am wrong or how to help others may land here find bliss in Ember.js

Creating mocks with Breeze.js

Breeze.js is a powerful library you can leverage in your Single Page Applications.  It plays nicely with all other technologies, and is designed to provide rich client-side data.  You can easily it with your application, regardless of the tech stack.  Don’t believe me?  Prove otherwise.  The authors of Breeze.js have certainly shown you can in their samples – http://www.breezejs.com/samples – (Side note: check out the ESPN sample, whoever made it is a genius)

Mocks –

Most applications have need for mocks.  Mocks can be especially powerful when you are building out the front-end and the back-end isn’t entirely ready yet.  You can also use them for writing unit tests against data without having to populate from the server.  I won’t get into testing in this post because there are so many ways to test and the tests can be very opinionated.

The only requirement for mocks is that you need to have your metadata in place first, either from the server or as the Breeze.js authors mention in the docs you can also get a snapshot of your metadata and pass it in when mocking. This is a great way to iterate and update your models. (Reference – http://www.breezejs.com/documentation/load-metadata-script)

Example –

function loadMocks (manager) {
    var personMockOne = manager.createEntity('Person', { id: 1, firstName: 'John', lastName: 'Smith' });
    var companyMockOne = manager.createEntity('Company', { id: 1, name: 'Acme Inc.' });
    companyMockOne.employees.push(personMockOne);
}

That’s it! We now have mocks we can run our tests against or build out our pages. Calling loadMocks() and passing in our manager will add the mocks to our entity collection and we can start testing. We pass in the manager to keep our function anonymous, and in the above example I am adding the employee mock to the company’s employees collection, but we could just as easily create the company and then set the company property on the person to companyMockOne. Example –

var companyMockOne = manager.createEntity('Company', { id: 1, name: 'Acme Inc.' });
var personMockOne = manager.createEntity('Person', { id: 1, firstName: 'John', lastName: 'Smith', company: companyMockOne });

You will notice when using this technique that the entityState of the entities are added. If you have logic in your page related to saving or cancelling changes, this could potentially trigger your UI to think the mocks need to be saved. We can easily get around that as well by calling acceptChanges() on the entityAspect of the entity. Example –

var companyMockOne = manager.createEntity('Company', { id: 1, name: 'Acme Inc.' });
companyMockOne.entityAspect.acceptChanges();

This will let Breeze know that you are comfortable with the changes made to the company and they do not need to be persisted to back to the database. While you could also chain the entityAspect.acceptChanges() onto the end of the createEntity method, beware that this will no longer return the entity.

var companyMockOne = manager.createEntity('Company', { id: 1, name: 'Acme Inc.' }).entityAspect.acceptChanges();
// The next line will not console log our entity
console.log(companyMockOne);

I often use this method for create enumerations as well that aren’t strictly passed down from a server. This can be especially useful when using someone else’s API where they aren’t exposing all of the data you need. Last Example –

manager.createEntity('Priority', { id: 1, name: 'Severe', imageSource: 'severe.jpg' }).entityAspect.acceptChanges();

This can be especially useful if you are re-using the enum all over your application.

I hope you find this useful, please leave any feedback below, especially if you see any errors. Direct any trouble-shooting questions to StackOverflow.com, and check out the Breeze.js UserVoice for feedback or feature requests.

Best parts about Durandal

I wanted to start a quick series dedicated to what makes Durandal so powerful to yield.

Part 1 – 

The Compose binding

With Durandal, you can dynamically load views and AMD modules directly from the DOM.  Why is this important?

  1. You can separate your views and modules into the smallest bits of (re-usable) code needed.
  2. Render your content more dynamically.
  3. You can easily instantiate and show either Singleton objects or Constructors.  (wait what?)

Separating your code

Imagine you want to create ‘n’ number of widgets that are in charge of their own visibility, data-fetching, and data-binding.  Easy.  Using the compose binding with a foreach, you can instantiate the modules in your view model and use the DOM to render them.

View –

<ul data-bind="foreach: widgets">
     <li data-bind="compose: widgetPath"></li>
</ul>

View Model –

define([], function () {
    var widgets = ko.observableArray();
    function initializeViewModel() {
        widgets.push(new Widget('Compose a widget module', 'viewmodels/exampleone'));
        widgets.push(new Widget('Compose a widget view only', 'exampletwo'));
    }
    function activate() {
        initializeViewModel();
    }
    function Widget(title, path) {
        var self = this;
        self.Title = title;
        self.widgetPath = path;
    }
});

What did we just do?

1. When we initiated the view model, we added two widgets into an observable array containing widgets.
2. The first widget is a path to a view model, which Durandal finds an associated view for and properly recognizes as part of a module.
3. The second widget is a path to a view, with no corresponding view model.

Whats interesting to note here is that in the first widget with a corresponding view model, Durandal helps us by creating a context around that view that is bound to the view model. This means if we reference something in the view model that Knockout and Durandal bind any related view elements to that instance of the view model. This is most ideal when not using singletons, as the every instance of a singleton will be bound to the same context.

In the second widget we are simply binding to the current context, which in this case would be the widget.  This is derived from the foreach binding that the widget is nested inside of, so you could easily bind to the title property or you could also reference the parent context using the Knockout $parent reference.

The reason $parent would not work in the first example is that the new context does not directly know who the parent is.  What if we wanted it to?  That’s easy as well, using activationData

Activation Data –

Using the activationData option of the compose binding, we can inject data or even context into the composed view model.  This is an excellent way of injecting dependency, and I could go on for hours on the various ways you can use this in your application, but let’s keep it simple and show an example.

Let’s bind our view up to widgets using Knockout’s containerless binding –

<!-- ko foreach: widgets -->
    <!-- ko compose: { model: widgetPath, activationData: { data: $data } } -->
    <!-- /ko -->
<!-- /ko -->

You’ll notice that I passing an object into the compose binding that contains a model and activationData, which contains an object of it’s own. You can read more on the Durandal website on the various parameters (http://durandaljs.com/documentation/Using-Composition.html) but basically the model is declaring that at that path, there is a view model to use for binding. Durandal automatically finds the corresponding view, and then injects our activationData into the view model. To intercept it, you only need to have a parameter in your activate method of the widget. Notice I am injecting $data, which basically just injects the current context into the view model. You could just as easily inject strings, observables, and even parent contexts.

Grabbing the data in our widget’s view model –

define([], function () {
    var thisContext = ko.observable();
    function activate(activationData) {
        // Set thisContext equal to the injected data
        thisContext(activationData.data);    
    }
    function Widget(title, path) {
        var self = this;
        self.Title = title;
        self.widgetPath = path;
    }
});

Now you can bind thisContext in the view however you want. A solid strategy is to use the with binding in your view that is set to thisContext, that way if for some reason your view model is instantiated without data it will just appear empty as opposed to breaking your bindings.

That’s it! Feel free to leave comments if you notice any problems or have any suggestions or questions. If you have any Durandal questions please direct them to StackOverflow.com or the Durandal.js Google Group, where the active community will help resolve them.

Consuming an API is a Breeze

Having trouble getting your new JavaScript libraries to play together nicely?  Want to see how you can use Breeze.js and Knockout.js to consume any API, ever, since the history of your browser?  Then look no further…

Why?

Checking out new JavaScript libraries and Frameworks can be scary.  Do you have a back-end already in place and just want to see what you can do on the front-end with Breeze.js and Knockout.js?  This sample / walk-thru is served only with an API, ESPN’s Developer API to be specific.  The only thing we do on the server here is server up our view from a Durandal.js starter app.  I choose Durandal.js because it is an extremely fast way to get a new project up in running, and provides a working app that needs only a few minutes to transform into an app of your own.

You can grab a working sample here of the finished code – http://github.com/PWKad/BreezeAPIOnlyKO (Note: this project uses NuGet package restore – read more about it here if you are unfamiliar http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages)

Breeze.js is an open-source JavaScript library from the established and well-respected team at IdeaBlade aimed at providing rich client-side data to your JavaScript apps.

  • Handles caching your data in the browser
  • Keeps track of changes to your JavaScript entities (and supports canceling those changes easily!)
  • Provides Linq-style queries in JavaScript

Knockout.js is an open-source JavaScript library created by Steve Sanderson to provide data binding all the way back to IE 6 (!!!!!)

  • Utilizes the MVVM pattern
  • Is an easy bolt-on to any project (Knockout is only concerned with binding data and keeping your view up-to-date)
  • Plug-ins are available to tackle any problem you have, and scale easily

Summary – 

The objective of this walk-thru is to help new to intermediate level JavaScript developers understand Breeze.js better and get a glimpse of the functionality when coupled with Knockout.js.  We will create a new project, add basic dependencies, set up Breeze to use with any API, create a JSON results adapter to map complex data structures, and bind our data to the view.

This is an open-source sample so if you see a problem feel free to make a pull request.  If you see a typo or something that just isn’t right feel free to leave a comment, or even send me a message either on here or on GitHub – pw kad

Technologies used –

Breeze.js – http://www.breezejs.com/

Knockout.js – http://knockoutjs.com/

Durandal.js – http://durandaljs.com/ – (Use the starter kit to get a JavaScript app up and running extremely fast)

Twitter Bootstrap – http://getbootstrap.com/2.3.2/

Getting Started – 

As a note, I use Visual Studio 2012 as my text editor for familiarity and ease-of-use. Let me know if you see any errors or have any helpful hints in the comments.

Create our new project – 

The Durandal Starter Kit is available at http://durandaljs.com/pages/downloads/ as a free download and also via http://www.asp.net/single-page-application/overview/templates/durandaljs-template as the SPA template (Note: Durandal 2.0 is now released, this project currently uses Durandal 1.2)

Open VS2012 and create a new ASP.NET MVC 4 application.  You can either create an Empty project and use NuGet to get the Durandal Starter Kit or install the template listed above and use Durandal SPA Project from the available templates window.

Creating a Durandal Starter Kit project

Creating a Durandal Starter Kit project’

We need to add a directory to our ‘App’ folder for the services we will use – App > services - This is where we will place our JavaScript files for getting data, creating the models, and any other JS files that are not view models.

Adding dependencies – 

Right click on our newly created project and choose Manage nuget packages… this will allow us to add our dependencies quickly and easily.

Choose the online option on the left of the pop-up to search online for available packages and in the top right search box type breeze to search for Breeze.js.  Install the Breeze for ASP.NET Web Api Projects package.  This package will add Breeze.js to the scripts folder, but it will also add some server-side stuff that we won’t be using.  (Basically if we were creating this project to serve up data as well as consume it we would need this additional library to make life easier, but since we will only be consuming the API we don’t need to worry about it)

Feel free to take a look in the scripts folder and check out our new dependencies.  Q.js is a promises library that Breeze uses to perform Asynchronous operations, such as querying.  If Sammy.js is in there, it was provided by our Durandal Starter Kit to help with routing and navigation (Note: Durandal 2.0 does not use the router plug-in including Sammy.js for routing nor navigation)

The only thing in the Controllers directory should be our Durandal controller, which will serve up our initial view.  The only thing in the Views folder are the splash page Durandal uses when loading up and an Index.cshtml file to host our Single Page App on.

Adding services – 

Inside of our services directory we need to add three JavaScript files (modules) –

First, let’s add our datacontext.js to the App/services folder.  This is requiring two services we haven’t finished setting up yet, (model and jsonResultsAdapter) so this won’t yet compile properly.

define(['services/model', 'services/jsonResultsAdapter'],
    function (model, jsonResultsAdapter) {

    });

Note on AMD (Asynchronous Module Definition) –

The define() statement defines the beginning of a module and is used to inject dependencies.  In this case we are using system/durandal and log system messages, so we require it and let our module know it can call it by using system

We will be using the model and jsonResultsAdapter in this module so we need to require them. Let’s add some basic functions to our datacontext

        var EntityQuery = breeze.EntityQuery;
        function returnResults(data) {
            return data.results;
        }
        var datacontext = {
        };
        return datacontext;
        function getLocal(resource, entityType, ordering) {
            var query = EntityQuery.from(resource)
                .toType(entityType)
                .orderBy(ordering);
            return manager.executeQueryLocally(query);
        }
        function queryFailed(error) {
            var msg = 'Error retrieving data. ' + error.message;
            console.log(msg);
        }

The EntityQuery variable will negate our need to call breeze.EntityQuery for each query we write.

The datacontext object we are creating is used to expose our functions to other modules that require it when it is returned.

getLocal is just a helper function to get local instances of an entity.

queryFailed is just a helper function logging errors in the console.

Setting up Breeze in our DataContext – 

We need to set up Breeze inside our datacontext

        var serviceName = "http://api.espn.com/v1/sports/baseball/mlb";
        var ds = new breeze.DataService({
            serviceName: serviceName,
            hasServerMetadata: false,
            useJsonp: true,
            jsonResultsAdapter: jsonResultsAdapter
        });
        function configureBreezeManager() {
            var mgr = new breeze.EntityManager({ dataService: ds });
            return mgr;
        }
        var manager = configureBreezeManager();
        model.initialize(manager.metadataStore);
        var metadataStore = manager.metadataStore;

This sets up a data-service, letting Breeze know that we don’t have any meta data available and will have to make our own and also let’s Breeze know we are going to use a custom jsonResultsAdapter.  We haven’t yet created it, but it is being required at the top of our datacontext in our define statement so it is available to us inside of it.

Next we need to create a model.js in our App/services folder –

define(['configuration'], function (config) {
    var DT = breeze.DataType;
    var model = {
        initialize: initialize
    };
    return model;
});

As you can see, we are revealing a function called initialize that initializes our entity models. We could have put this into our datacontext module but in the interest of the separation of concerns principle we want to keep this module separate.

    function initialize(metadataStore) {
        metadataStore.addEntityType({
            shortName: "NewsItem",
            namespace: "ESPN",
            dataProperties: {
                id: { dataType: "Int64", isPartOfKey: true },
                teamId: { dataType: "Int64" },
                headline: { dataType: "String" },
                description: { dataType: "String" },
                source: { dataType: "String" },
                imageSource: { dataType: "String" },
                imageCaption: { dataType: "String" },
                imageCredit: { dataType: "String" },
                link: { dataType: "String" }
            },
            navigationProperties: {
                team: {
                    entityTypeName: "Team", isScalar: true,
                    associationName: "Team_NewsItems", foreignKeyNames: ["teamId"]
                }
            }
        });
        metadataStore.addEntityType({
            shortName: "Team",
            namespace: "ESPN",
            dataProperties: {
                id: { dataType: "Int64", isPartOfKey: true },
                location: { dataType: "String" },
                name: { dataType: "String" },
                abbreviation: { dataType: "String" },
                color: { dataType: "String" }
            },
            navigationProperties: {
                newsItems: {
                    entityTypeName: "NewsItem", isScalar: false,
                    associationName: "Team_NewsItems"
                }
            }
        });
        metadataStore.registerEntityTypeCtor(
            'Team', null, teamInitializer);
        function teamInitializer(team) {
            team.fullName = ko.computed(function () {
                var loc = team.location();
                var name = team.name();
                return loc + ' ' + name;
            });
            team.showNews = ko.observable(false);
        }
    }

If you remember earlier in our datacontext we passed the metadataStore into the model.initialize() function. model.initialize(manager.metadataStore);. In the model we are adding types ‘Team’ and ‘NewsItem’. These entities have navigation properties linking them, which we set up with an association. This will allow us to easily bind the data in the view, and will remove the need to make additional calls to the server.

Finally, we want to register a custom property on the Team called ‘fullName’ which is a computed observable. We will use this in the view to represent a team’s location and name (ie. Texas Rangers) We are also setting an observable called showNews that we will use to flag whether the team’s news is being shown. Every time an entity is pulled in from the server or created these functions will be executed.

Now let’s set up our API calls in the datacontext

        var myAPIKEY = "qubdkem5nhuctxtxghkx32nm";
        var getTeams = function (teamsObservable, forceRemote) {
            if (!forceRemote) {
                var p = getLocal('Teams', 'Team', 'id');
                if (p.length > 0) {
                    teamsObservable(p);
                    return Q.resolve();
                }
            }
            var parameters = makeParameters();
            var query = breeze.EntityQuery
                .from("teams")
                .withParameters(parameters)
                .toType('Team');
            return manager.executeQuery(query).then(querySucceeded).fail(queryFailed);
            function querySucceeded(data) {
                var s = data.results;
                return teamsObservable(s);
            }
        };
        var getTeamNews = function (team) {            
            var parameters = makeParameters();
            var query = breeze.EntityQuery
                .from("teams/" + team.id() + "/news")
                .withParameters(parameters);
            return manager.executeQuery(query).then(querySucceeded).fail(queryFailed);
            function querySucceeded(data) {
                var s = data.results;
                var tempObs = ko.observableArray(s);
                // Since the news item has multiple categories and can be for multiple teams
                // we will set the team explicitly to the team we are searching for.
                // We could set it to each team, but this is a simple example.
                ko.utils.arrayForEach(tempObs(), function (newsitem) {
                    newsitem.teamId(team.id());
                });
                return true;
            }
        };
        function makeParameters(addlParameters) {
            var parameters = {
                apikey: myAPIKEY
            };
            return breeze.core.extend(parameters, addlParameters);
        }
        function returnResults(data) {
            return data.results;
        }

There is a lot going on here so let’s get down into more detail –

myAPIKEY is an API key provided by ESPN.  You can register for your own at http://developer.espn.com/

getTeams and getTeamNews are two functions that perform Breeze EntityQuery’s.  You can learn a lot more about structuring these queries on Breeze’s website, and I won’t cover exactly how they work here (would make this walk-thru much longer) but understand that these queries are structured to check the local cache for entities, and if there are none they will go hit the API.

makeParameters is an internal helper function that creates parameters.  The ESPN developer API requires a key to be passed, and we are extending any additional parameters passed in.  This will make our API call look something like this –

http://api.espn.com/v1/sports/baseball/mlb/teams/2/news?apikey=[apiKey will show up here]

Finally, there is a returnResults function that we will use to return the data.results from the callback.

We need to expose those functions to any other module that is requiring the datacontext, so adjust the object we are returning in our datacontext.

        var datacontext = {
            getTeams: getTeams,
            getTeamNews: getTeamNews
        };
        return datacontext;

Now that our datacontext is ready to go, we need to set up our jsonResultsAdapter.js

define([], new breeze.JsonResultsAdapter({
    name: "ESPN",
    extractResults: function (data) {
        var results = data.results;
        if (!results) throw new Error("Unable to resolve 'results' property");
        return results && (results.headlines);
    },
    visitNode: function (node, mappingContext, nodeContext) {
        if (node.headline) {
            if (node.images.length > 0) { 
                node.imageSource = node.images[0].url;
                node.imageCaption = node.images[0].caption;
                node.imageCredit = node.images[0].credit;
            }
            else {
                node.imageSource = '../content/images/blank_image.png';
                node.imageCaption = 'none';
                node.imageCredit = 'no credit';
            }
            node.link = node.links.web.href;
            return { entityType: "NewsItem" };
        }
    }
}));

This is a custom adapter we register in our datacontext to map the results from a complex JSON structure.  You can read more about how it works in the Breeze docs, but here is a basic breakdown –

name assigns a namespace.  If you remember earlier when we created the entity types in our model we assigned them to a namespace.

extractResults makes sure that the data returned has a results property and then checks to see if there is a headlines property.  If so, we create entities out of the results.  The reason we check for a headlines is because it is a unique property on the news objects being returned, so we know that if a result has a property headlines it should be mapped to a NewsItem.  When a news item is created we also need to map some of it’s properties.

Alright, that was a lot of JavaScript.  Let’s see some results –

Note – The below portion of this walk-thru doesn’t go into a lot of detail yet.  Give me a few days and I can explain it in more detail.

Delete the code inside your home.html in your App/views folder. Replace it with the below HTML –

<h3 class="teams-header">Team News - <img src="http://a.espncdn.com/i/apis/attribution/espn-api-black_150.png" /></h3>
<div class="accordion" id="sports-accordion" data-bind="foreach: teams">
  <div class="accordion-group">
    <div class="accordion-heading" data-bind="style: { backgroundColor: '#' + color() }" >
        <a class="accordion-toggle team-brief" data-toggle="collapse" data-parent="#sports-accordion" 
            data-bind="attr: { href: '#' + abbreviation() }" >
            <p><span data-bind="text: abbreviation"></span> - <span data-bind="text: fullName"></span></p>
        </a>
    </div>
    <!-- ko if: showNews() === true -->
    <h5 data-bind="visible: newsItems().length === 0">Fetching news...</h5>
    <div data-bind="attr: { id: abbreviation }" class="accordion-body collapse in">
      <div class="accordion-inner">
        <ul class="media-list" data-bind="foreach: newsItems">
            <li class="media">
                <a class="pull-left" data-bind="attr: { href: link }">
                    <img class="media-object" data-bind="attr: { src: imageSource(), title: imageCredit }" />
                </a>
                <div class="media-body">
                    <h4 class="media-heading" data-bind="text: headline"></h4>
                    <blockquote>
                        <p data-bind="text: description"></p>
                        <small>from <cite title="Source" data-bind="text: source"></cite></small>
                    </blockquote>
                </div>
            </li>
        </ul>
      </div>
    </div>
    <!-- /ko -->
  </div>
</div>

This is a Twitter Bootstrap accordion bound to our Knockout data.

Now replace all of the home.js code in our App/viewmodels folder with the below –

define(['services/datacontext', 'viewmodels/shell'], function (datacontext, shell) {
    var teams = ko.observableArray();
    var bindEventToList = function (rootSelector, selector, callback, eventName) {
        var eName = eventName || 'click';
        $(rootSelector).on(eName, selector, function () {
            var team = ko.dataFor(this);
            callback(team);
            return false;
        });
    };    
    var toggleTeamNews = function (team) {
        if (team.showNews() === true) { team.showNews(false); }
        else {
            if (team.newsItems().length === 0) {
                datacontext.getTeamNews(team).fail(queryFailed);
            }
            team.showNews(true);
        }
    };
    var viewAttached = function (view) {
        bindEventToList(view, '.team-brief', toggleTeamNews);
    };
    var initLookups = function () {
        datacontext.getTeams(teams).fail(queryFailed);
    };
    function queryFailed(error) {
        console.log(error.message + " - Query failed; please try it again.");
    }
    var activate = function () {
        initLookups();
        return true;
    };
    var home = {
        activate: activate,
        teams: teams,
        viewAttached: viewAttached,
        shell: shell
    };
    return home;
});

That’s it! Run our app and you will see a list of MLB teams, with the names on top of their team color returned from the server. Clicking on any of the teams will go fetch their news, and once we have fetched it Breeze is caching the NewsItem’s so we can hide or display them as we see fit, without having to hit the server again.

JavaScript Comparisons Pt. 1 – Data-Binding – Knockout.js vs Angular.js

I want to post some thoughts I have of various JavaScript libraries / frameworks in a short series that is direct and to the point.

While these posts may be full of opinions, they will be as truthful as possible and relevant to the point.

Test 1 – Data-binding

What do I expect from my two-way data-binding?

  1. Data is bound from the view to the * (controller, viewmodel, w/e)
  2. Binding is as efficient as possible (don’t waste my resources)
  3. Context / Scope is easy to understand
  4. Easy to use for a developer – the end-user doesn’t care how well data-binding occurs…

Comparisons – 

Knockout –

Pros –

  1. Data is bound to the view model.
  2. Binding occurs on blur, unless specificied
  3. Context is easy to set (with or foreach bindings give nested context easily)
  4. A dynamic nesting tree of data-binds is available, and trouble-shooting info is always available in console

Cons –

  1. Bindings can easily break when not handled properly (ie. binding to ID before it is available)
  2. Must use an additional data-bind attribute ‘valueUpdate: onKeyPress’ for per-key updates or use a custom binding handler
  3. Must understand $parent, $parents[1], and $root for contextual purposes
  4. Often a simple parans can be the difference between bindings working and two hours of work for a new developer

Angular –

Pros –

  1. Binding is simple and doesn’t require understanding of getters and setters
  2. Binding is on key press by default
  3. Settings what is within $scope is more explicit in the controller
  4. Binding requires no parans(!!!)

Cons –  (at least 1 week into a project)

  1. Notification of broken binds is not apparent
  2. Refactoring every binding in the view occurs every key stroke
  3. Contextual bindings aren’t as clear
  4. Bindings require twice as much mark-up (ng-click, ng-model, etc…)

In closing, Knockout serves a singular purpose (data-binding, rich UI’s) that can easily replace many of the functions that we as interface developers have relied upon jQuery for in the past.  Angular takes on many more tasks in addition to data-binding and therefore seems to have a very sufficient ability to bind data while taking it’s own approach.

Overall winner :  Knockout

Knockout knows what it’s main purpose is – data-binding and creating a rich UX.  Angular is good at both but seems to lean towards an all or nothing mentality, and does not support many dev favorites –

  1. Doesn’t support Knockout
  2. Doesn’t (easily) support Twitter Bootstrap