Hello, we are RealCrowd, and we use C#

tl;dr – Do you love the web, JavaScript, CSS and industry changing products? – We’re hiring. Send an email to jobs@realcrowd.com.

That’s right, a one year old YCombinator company is hiring web developers and we use Microsoft technology. Perhaps hell has frozen over. Maybe pigs have evolved and now use those cute little tails as props for vertical takeoff and landing. Have us founders gone mad?

Some days I feel like we should be part of a support group.


“Hello, we’re RealCrowd, and we use C#,” we say nervously.

“Hello RealCrowd!” the group responds in kind.


Any time we meet up with peers or talk with investors we end up having the tech stack “discussion”. Everyone assumes our product is built on Ruby on Rails or Scala or Node.js or [insert-other-hip-tech-here]. What was meant as idle chit-chat turns into a debate. Our technical prowess is questioned. We have to defend our choices. Why is this even a discussion?

While common and respected in game development, financial services and corporate America, C# and the Microsoft tech stack is shunned by the Silicon Valley startup ecosystem. It is the forbidden fruit. One must not indulge, for fear of being corrupted by the snake that is only out for your blood. We don’t buy into this rhetoric.

Our code is fully asynchronous around I/O events using async/await. We use Azure’s PaaS services for very little operational overhead. But we also abstract away those services so we can change our persistence/communication/hosting providers in the future. We practice continuous integration. We have tests, and even run them occasionally. We have automated build and deploy systems. We monitor performance and stability like a hawk. We use the open source branch/merge/pull-request development style with code reviews around everything. We do all the things one would expect in a modern, fast-moving development shop.

But let’s back up for a minute. Who is this mysterious company building products on such uncool/forbidden technology in a cool/modern way?

We are RealCrowd. We operate in the super uncool, stodgy, investment-banker-saturated world of commercial real estate investing. It is Serious Business with huge sums of money at risk. Our paying customers have done Billions of dollars of business. They own the office building you work in, the apartment complex you live in, and the retail buildings where you spend your hard earned cash — that is, unless you are like me and never leave the comfort of your Aeron chair. I understand. It’s hard to fight the allure of Amazon Prime. Then again, they even own some of the warehouses Amazon uses. But I digress…

About a year ago the only way an individual could directly own such real estate assets was to be in the right place at the right time and know someone at a company buying a building. But not anymore! Because of the JOBS Act, partial ownership of these assets is now available on the public internet via RealCrowd. We are a marketplace that connects investors to companies offering real estate investments (operators). We handle the details of the investment process and digitally ferry thousands of pages of paperwork back and forth for every deal.

We save trees. We make people’s lives easier. We make everyone more money. And we have fun doing it.

Boy have we been surprised by how much investors and operators love this. To date investors on our site have invested over $17 Million in real estate valued at over $500 Million. See. It’s Serious!

It is the Serious nature of the business that led us down the road to Microsoft technology. We wanted to blend stable technology with current rapid development practices. We looked at Java, the other obvious choice of the Serious, but ultimately decided on Microsoft tech with C#.

Our server stack is C#, ASP.NET MVC, ASP.NET WebApi, running on Azure utilizing their NoSQL store, distributed queues, distributed cache, and other modern tools. We’ll move to ASP.NET vNext once it’s ready for Serious Business. We’re an API-first development shop, and take pride in building secure, high quality, and performant software.

Our front end is built on a core of AngularJS and Bootstrap. It is responsive and designed to present a fully featured and useable mobile web experience.

Come work with us, email jobs@realcrowd.com and join our support group for outcast technologists.

3 Simple Design Practices for Maintaining Sanity at a Start-up

Startups often have a barebones team — one marketer, one engineer, one customer service rep, and so on. It’s always a skeleton crew, all the time.

Each member takes on a lot of work that would in larger organizations be delegated. This means wearing a lot of hats, learning on the fly, and pushing workloads to maximum capacity.

While exciting and fulfilling, the structure carries an inherent danger, sometimes referred to as mental burnout. Take on too much work, spread yourself too thin, and suddenly quality takes a hit and productivity dives.

At RealCrowd, I’m the Director of User Experience and the one designer in house. Like everyone, I make keeping sanity in check — while being as efficient and productive as possible — a big priority. It’s a delicate balance.

Here are three simple processes I’ve implemented, along with the rest of the RealCrowd team, to mitigate mental burnout.

1. Enlist the Help of Non-Designers

We are fortunate to have a CEO and business team who have Photoshop and Illustrator installed on their machines and know how to use them. This has made it easy for them to create fliers, banners, and other collateral.

Once they have prototyped a design that they feel good about, I’m able to perform a quick design review or quick tweak to finalize the design. This helps speed up the design process and untangle competing deadlines between application and marketing needs. This also allows me to know which files should be templatized for reuse by the team so that I can focus on designing for the harder design problems.

2. Create a Product Design Backlog List

Coming from the corporate world, product backlogs can seem daunting, especially for a team that wants to be agile and flexible. Our Product Design Backlog contains design priorities that cover both product and marketing design projects.

There are so many projects that the product team, the business team, and I want to complete. Some need to be planned or designed prior to our weekly scrum. We now have a list of conceptual, redesign and branding work that we plan to complete.

A backlog list makes it easier to visualize similarities in projects, prioritize, and see when we need to call in additional help or scale back.

3. Assign Days for Important Aspects of the Job

At a startup, designers have to do more than deliver wireframes and high-resolution designs for the application. Depending on the day, I may need to help update our homepage, create a mobile-only solution, create an ad banner, or create an infographic. There’s a lot to do, but if you’ve already created your backlog, you probably see there are a few themes – product design, marketing design, and UX-led initiatives.

Once you know what’s in your backlog and have a good idea of your velocity, consider setting aside specific days for your major themes.

Currently, my week looks like this: product design on Monday, Tuesday, Wednesday, marketing on Thursday, and design-led initiative on Fridays. As our backlog shifts, this may change, but for now, it’s working well.

These quick tips have really helped me through times when I was close to burnout. If you’re a designer, hopefully you’ve learned a few tips that will make your design process smoother and more productive.

If you’re a RealCrowd user, hopefully you’ve noticed some of the changes that we’ve made with the help of these methods. As always, we’re itching for any feedback you might have, so don’t hold out. We’d love to hear it.


 

For more information about how you can fund your deals through RealCrowd, access the platform’s investor and transraction management solutions, or become a participating investor visit www.realcrowd.com or email info@realcrowd.com.

 

RESTful Realtime

RealCrowd is an online investment platform for commercial real estate. Investors can purchase equity in institutional quality properties offered by top notch investment companies (called operators). These operators identify the asset they want to buy, secure loans, and raise money from investors to buy it. RealCrowd lets operators do the money raising part easily online. Because of the nature of real estate transactions there is a limited time window for raising funds and investors need to decide fairly quickly if they are going to participate.

When we send out the announcement for a new investment listing we get a stampede of visitors. These visitors will usually sit on the investment page for 10 minutes or more as they review detailed financial documents and other information about the investment, contemplating a significant decision. Often times investments are made by others when an investor has the page open. We wanted to avoid the poor user experience of an “out of stock” situation at investment time so we keep the critical investment information up to date in real time. An investor on the site today sees the updated amount available even as investments are made by other people. We also plan to support various social features in the future, which could mean user-to-user communication or other interactions, and these kinds of features will require realtime behavior, so we are setting ourselves up to easily expand into that later.

Approach

Nowadays there are about 1,000 different services and components you can use to do realtime. We decided to use GRIP to realtime-enable our API. GRIP was created by the folks at Fanout and is a simple yet flexible way of designing a realtime system. Basically, client connection management is isolated to a dedicated proxy (such as Pushpin) and our API communicates with that proxy to send updates to users. As we’re an “API first” company, we found this approach more attractive than alternatives like Socket.IO because our public interface stays clean, simple, and under our control.

Since our backend code is primarily written in C#, we created a GRIP library for .NET. It is packaged in NuGet as RealCrowd.Grip. We hope you find it useful!

Implementation

Our investment API now supports long-polling for straightforward and durable realtime push. In sticking with our RESTful philosophy, we use the ETag and If-None-Match headers to detect for changes. If the client provides an If-None-Match header that matches the data known by the server, then the request hangs open until the data changes, at which point the server can respond with new data instantly. If enough time passes with no change, the server responds with code 304 Not Modified.

What’s great about this protocol flow is that it’s identical to a traditional check for resource modification. Some browsers like Chrome will even include If-None-Match on AJAX requests if an ETag was received in an earlier response, making client side code super simple.

For example, a client may request investment information against our realtime domain stream.realcrowd.com:

GET https://stream.realcrowd.com/api/v1/investment/fortdaviscenter

Since the If-None-Match header was not supplied, the server responds immediately:

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "320000000"

{
  "data": {
    "minInvestment": 0,
    "investmentIncrement": 0,
    "investmentId": "fortdaviscenter",
    "commitmentsDueDate": 0,
    "totalEquityAmount": 330000000,
    "totalUserCommitment": 0,
    "description": null,
    "projectedIrrHigh": 0.0,
    "targetAmount": 330000000,
    "totalCommitments": 320000000,
    ...
  }
}

The client can check for updates by performing the same request again, but this time including an If-None-Match header containing the value of the ETag header received in the previous response from the server.

GET https://stream.realcrowd.com/api/v1/investment/fortdaviscenter
If-None-Match: "320000000"

At this time we’re simply using the commitment level as the ETag. The ETag value is opaque to the client, though, so we can always make a more advanced value in the future if we choose (such as a digest of the entire object).

If no commitment change occurs for awhile, the server times out the request and responds with 304:

HTTP/1.1 304 Not Modified
Content-Length: 0
ETag: "320000000"

Otherwise, if more money is committed, then the server will respond with the latest data. Here we’ve gone from $3.2M committed to $3.3M:

HTTP/1.1 200 OK
Content-Type: application/json
ETag: "330000000"

{
  "data": {
    "minInvestment": 0,
    "investmentIncrement": 0,
    "investmentId": "fortdaviscenter",
    "commitmentsDueDate": 0,
    "totalEquityAmount": 330000000,
    "totalUserCommitment": 0,
    "description": null,
    "projectedIrrHigh": 0.0,
    "targetAmount": 330000000,
    "totalCommitments": 330000000,
    ...
  }
}

If a client receives a 304, it simply makes the same request again. This endpoint is being used today on RealCrowd property pages to ensure the latest commitment information is displayed.

Code

Making the investment endpoint realtime capable only took a couple of changes. First, near the start of our endpoint handler, we now check for the If-None-Match header and respond with an application/grip-instruct message if it matches the value on the server. This tells the GRIP proxy to keep the client on the line in a long poll, but doesn’t require our API servers to maintain that connection. Otherwise, we set the ETag on the response we are building and continue processing as normal, in which case the GRIP proxy will simply return the response to the client.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var response = new HttpResponseMessage(HttpStatusCode.OK);
 
...
 
var serverETag = '\"' + data.ETag + '\"';
var clientETag = this.Request.Headers.IfNoneMatch.FirstOrDefault();
 
if (clientETag != null && clientETag.ToString() == serverETag)
{
    var gripPrefix = Configuration.Current.GripPrefix;
    var gripProxies = RealCrowdApi.Configuration.Current.GripProxies;
 
    if (gripProxies != null && this.Request.CheckGripSignature(gripProxies))
    {
        var instruct = new RealCrowd.Grip.Instruct();
        instruct.CreateResponseHold(gripPrefix + "investment-" + id, data.ETag,
            "application/json", "");
        instruct.Response.Code = 304;
        instruct.Response.Headers.Add(new KeyValuePair<string, string>("ETag", serverETag));
        response.Content = new StringContent(instruct.ToString(), Encoding.UTF8,
            "application/grip-instruct");
    }
    else
    {
        response.StatusCode = HttpStatusCode.NotImplemented;
        response.Content = new StringContent("Error: Realtime endpoint not supported.\n");
    }
 
    return response;
}
 
response.Headers.ETag = new EntityTagHeaderValue(serverETag);
 
...

If the request should be held open, we bind it to a channel name specific to the investment id. Channels are a lot like namespaces in Socket.IO. We also specify the response information that the GRIP proxy should use in the event of a timeout. The CheckGripSignature() method is handy, as we can use it to detect if an incoming request actually came from a GRIP proxy. If the request didn’t, then we respond with code 501 Not Implemented. We use this for our local workstation development environment so the client hitting that endpoint will not attempt any polling unless the developer has the GRIP proxy running and is working with the realtime components.

The above code is enough to make requests hang open and timeout properly. This brings us to the next part: publishing asynchronous updates. We already had a background job that ran anytime investment data changed, so all we needed to do was publish HTTP response data to the GRIP proxy from the job handler.

1
2
3
4
5
6
7
8
9
10
11
...
var gripPrefix = Configuration.Current.GripPrefix;
 
var id = Convert.ToString(data.TotalCommitments);
var responseFormat = new RealCrowd.Grip.HttpResponseFormat("application/json",
    await content.ReadAsStringAsync());
responseFormat.Headers.Add(new KeyValuePair<string, string>("ETag", data.ETag));
 
await gripPublisher.PublishAsync(gripPrefix + "investment-" + commitment.InvestmentId, id,
    null, responseFormat);
...

In the above code, content is an ObjectContent that we must read from to create an HttpResponseFormat to publish. That’s it for the server side.

On the browser side, we’re using Pollymer to access our API. It’s a JS library that contains various AJAX conveniences for long-polling. Here’s the code we run on every investment page:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var req = new Pollymer.Request({ maxTries: -1, errorCodes: '500,502-599' });
var uri = realtimeApiRoot + 'investment/' + investmentId;
req.on('finished', function (code, result, respHeaders) {
    if ((code >= 200 && code <= 299) || code == 304) {
        var etag = null;
        for (var key in respHeaders) {
            if (!respHeaders.hasOwnProperty(key)) {
                continue;
            }
            if (key.toLowerCase() == 'etag') {
                etag = respHeaders[key];
            }
        }
        if (!etag) {
            console.log("failed to get ETag: headers=" + JSON.stringify(respHeaders));
            return;
        }
 
        process(result);
        reqHeaders = { 'If-None-Match': etag };
        req.start('GET', uri, reqHeaders);
    }
});
req.start('GET', uri);

What this does is create a request object that is configured to retry failed requests indefinitely (except code 501). On success, process the result, and of course deal with any ETag-related things and start another poll. Notice that the request object is reused. This ensures we benefit from Pollymer’s randomized delay behavior, preventing connection stampedes on events where clients would get simultaneously disconnected such as load balancer, server, or router restarts.

Conclusion

Real estate may be an old industry but we pride ourselves in building a cutting edge service. What do you think of our RESTful realtime API approach? If you’re using .NET and want to do the same thing, be sure to check out our GRIP library for .NET.

Discuss on Hacker News

The Wonderful Wizard of AngularJS

Boy am I diggin’ AngularJS. There are so many cool bits to it. And the bits that don’t exist are fun to build…once you get the hang of it that is. Case in point, a nifty little wizard module. We here at RealCrowd use wizards on a few pages in our app. They are a nice mechanism to guide users thru multi-step or complex tasks. Translating a complex UI component into an AngularJS module can be a bit tricky. But because of the modular approach we’ve taken to development, we were able to develop a fairly robust implementation. For those more interested in code than an dissertation, here is a shortcut to our Github.

I personally have been known to re-invent the wheel from time to time, but when I find a good simple plug-in I like to use it. RealCrowd is also a fan of responsive design and use Twitter Bootstrap. We therefore choose to use the unofficial third-party Bootstrap Wizard Plug-in to base our angular module on. However, the current version was designed for Bootstrap version 2.3.2 and we use version 3.0.0. There needed to be some slight modifications for this to work with 3.0.0. We have forked the current plug-in here with a fix and have also submitted a pull request to the source branch (Update: The fix has now been merged into the source branch).

As with most projects, things seem relatively simple when looking at the high-level view. We just need a directive to apply our wizard plug-in. However, when we consider the nuances of the UI, things get a bit more complex. What about the backward and forward buttons? We want to hide the backward at sometimes and the forward at others. What if we want to validate at each step? What if we want to call a web-service and not move forward until completed? And what if you want to do all these things and not have a bomb or spaghetti code go off? Well lucky for you that bomb already went off for us, so we went back and cleaned-up the mess and came up with what we believe is a nice flexible, straight-forward approach.

Before we get into building this module, it is recommended you have a basic understanding of AngularJS and directives. Things can get a bit technical, but if you understand the basics it should be pretty informative. Now let’s start with some mark-up to define our wizard. The Bootstrap Wizard Plug-in utilizes the official Bootstrap JQuery Tab plug-in, so we just have to include the Bootstrap stylesheets and javascript (note: We are using Bootstrap v3.0.0 which is quite different from the old v.2.3.2. If not using v3.0.0, you’ll have to do a bit of work to translate this):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    <div ng-app="SampleWizardApp" ng-controller="SampleWizardController">
      <ul class="nav nav-pills">
        <li class="active">
         <a class="active" href="#first" data-toggle="tab">
           <span class="badge">1</span>
           <span>First Step</span>
         </a>
       </li>
       <li>
         <a href="#second" data-toggle="tab">
           <span class="badge">2</span>
           <span>Second Step</span>
         </a>
       </li>
       <li>
         <a href="#last" data-toggle="tab">
           <span class="badge">3</span>
           <span>Last Step</span>
         </a>
       </li>
      </ul>
      <div class="tab-content">
        <div class="tab-pane active" id="first">
          <h2>Enter first step data</h2>
          <div class="form-group">
            <label class="control-label">First Name</label>
            <input name="firstName" class="form-control" type="text" 
              ng-model="user.firstName" />
          </div>
          <div class="form-group">
            <label class="control-label">Last Name</label>
            <input name="lastName" class="form-control" type="text" 
              ng-model="user.lastName" />
          </div>
        </div>
        <div class="tab-pane" id="second">
          <h2>Enter second step data</h2>
          <div class="form-group">
            <label class="control-label">Street Address</label>
            <input name="streetAddress" class="form-control" type="text" 
              ng-model="user.streetAddress" />
          </div>
          <div class="form-group">
            <label class="control-label">City</label>
            <input name="city" class="form-control" type="text" 
              ng-model="user.city" />
          </div>
          <div class="form-group">
            <label class="control-label">State</label>
            <input name="state" class="form-control" type="text" 
              ng-model="user.state" />
          </div>
          <div class="form-group">
            <label class="control-label">City</label>
            <input name="postalCode" class="form-control" type="text" 
              ng-model="user.postalCode" />
          </div>
        </div>
        <div class="tab-pane" id="last">
          <h2>Finish last step</h2>
          <div class="form-group">
            <label class="control-label">First Name:</label>
            <p class="form-control-static">{{ user.firstName }}</p>
          </div>
          <div class="form-group">
            <label class="control-label">Last Name:</label>
            <p class="form-control-static">{{ user.lastName }}</p>
          </div>
          <div class="form-group">
            <label class="control-label">Address:</label>
            <p class="form-control-static">
              {{ user.streetAddress }}
              <br />
              {{ user.city }}, {{ user.state }} {{ user.postalCode }}
            </p>
          </div>
        </div>
      </div>
      <div class="form-group">
        <div class="pull-right">
          <a class="btn btn-default">Back</a>
          <a class="btn btn-primary">Continue</a>
        </div>
      </div>
    </div>

So we basically are starting out with an ordinary tab layout with some buttons at the bottom. To be clear, all of the style classes used are from Bootstrap. When we use custom styling we will prefix our CSS classes with an ‘rc-‘. Because of Bootstrap’s many styling options, our tab control already looks more wizard-y than tab-y. Thanks Bootstrap! Next we need to start our wizard directive to wizard-ify the tabs’ behavior. In our directive we will need a controller to wrap the basic wizard features and track some state. We want to make the state available so we will make the controller available on the scope. This is similar to what we do for the rcSubmit controller (which we describe the ‘why’ and ‘how’ in Advanced AngularJS Form Validation). The start of our wizard looks something like this (A quick note on naming convention for those new to the blog; all our constructs are prefixed with ‘rc’ for ‘RealCrowd’. We use this as a namespace, the same way AngularJS uses ‘ng’):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
    var rcWizardDirective = {
     'rcWizard': function () {
       return {
         restrict: 'A',
         controller: ['$scope', function ($scope) {
 
           var self;
           var wizardElement;
           var wizardOptions = {};
 
           this.currentIndex = 0;
           this.firstIndex = 0;
           this.navigationLength = 0;
 
           this.forward = function () {
             self.onForward();
           };
 
           var onForward = function () {
             wizardElement.bootstrapWizard('next');
           };
 
           this.backward = function () {
             wizardElement.bootstrapWizard('previous');
           };
 
           var onTabChange = function (activeTab, navigation, currentIndex, nextTab) {
 
             self.currentIndex = nextTab;
             self.firstIndex = wizardElement.bootstrapWizard('firstIndex');
             self.navigationLength = wizardElement.bootstrapWizard('navigationLength');
 
             if (!$scope.$$phase) $scope.$apply();
           };
 
           var onTabClick = function (activeTab, navigation, currentIndex, clickedIndex) {
             return false;
           };
 
           var onTabShow = function (activeTab, navigation, currentIndex) {
 
             if (currentIndex > 0) {
               wizardElement
                 .find('.nav li:gt(' + (currentIndex - 1) + ')')
                 .removeClass("success");
               wizardElement
                 .find('.nav li:lt(' + currentIndex + ')')
                 .addClass("success");
             } else {
               wizardElement
                 .find('.nav li')
                 .removeClass("success");
             }
           };
 
           var updateWizard = function (options) {
 
             wizardOptions = options;
 
             if (wizardElement) {
               wizardElement.bootstrapWizard(options);
               self.currentIndex = wizardElement.bootstrapWizard('currentIndex');
               self.firstIndex = wizardElement.bootstrapWizard('firstIndex');
               self.navigationLength = wizardElement.bootstrapWizard('navigationLength');
 
               if (!$scope.$$phase) $scope.$apply();
             }
           };
 
           this.setWizardElement = function (element) {
             wizardElement = element;
             self = this;
             updateWizard({
               'onTabChange': onTabChange,
               'onTabShow': onTabShow,
               'onTabClick': onTabClick
             });
           };
         }],
         compile: function (cElement, cAttributes, transclude) {
           return {
             pre: function (scope, formElement, attributes, wizardController) {
               // put a reference to the wizardcontroller on the scope so we can use some of the 
               // properties in the markup
               scope.rc = scope.rc || {};
               scope.rc[attributes.rcWizard] = wizardController;
             },
             post: function (scope, element, attributes, wizardController) {
               // let the controller know about the element
               wizardController.setWizardElement(element);
               if (!scope.$$phase) scope.$apply();
             }
           };
         }
       }
     }
   };

As you can see we are just applying and configuring the Bootstrap Wizard plug-in to the element and wrapping some of its functionality (namely the ‘forward‘ and ‘backward‘ methods). The forward method is double-wrapped. This will be helpful later on. We also are providing access to some state (i.e. currentIndex, firstIndex, navigationLength) that will also be useful. You may notice we added a handler for the onTabClick events and return false. This is so the user can’t use the tab headings (now step headings) to navigate. Another handler we are using is onTabShow. We do this to add/remove a success CSS style class where appropriate which will allow us do some additional styling (Note: ‘success‘ is a contextual CSS class in Bootstrap). Now we just need to add a couple items to our markup to take advantage of our new directive (also don’t forget the reference to the Bootstrap Wizard plug-in):

1
2
3
    <div ng-app="SampleWizardApp" ng-controller="SampleWizardController" 
      rc-wizard="sampleWizard">
      <ul class="nav nav-pills">

77
78
79
80
81
82
83
84
85
86
87
88
89
      <div class="form-group">
        <div class="pull-right">
          <a class="btn btn-default" 
            ng-click="rc.sampleWizard.backward()"
            ng-hide="rc.sampleWizard.currentIndex > rc.sampleWizard.firstIndex">Back</a>
          <a class="btn btn-primary" 
            ng-click="rc.sampleWizard.forward()"
            ng-show="rc.sampleWizard.currentIndex < rc.sampleWizard.navigationLength">
            Continue
          </a>
        </div>
      </div>
    </div>

Now our wizard is behaving more like a proper wizard. The ‘Back’ and ‘Continue’ buttons not only work, they also hide themselves when they aren’t needed. This is the point where most blogs would probably leave you: with a simple directive that does basically what you want it to do. But that is always annoying because when you go to implement it there are all these practical requirements missing. In the case of this wizard, a big missing piece is validation.

Wizard validation is a bit tricky. At first it may seem easy: just place a form around the wizard and handle it like any other form. However, in a wizard, you don’t want to just validate the wizard as a whole, you want to validate it per step. And until a step is valid you want to prevent navigation to the next step. Luckily we have some experience with form validation and disabling UI while busy that will come in handy here. We will be able to use the rcSubmit controller to tap into the validation process, namely onSubmitComplete. Since we need to validate on each step there will be a rcSubmit controller for every step. In order for our rcWizard controller to be able to handle that, we need to provide a way to track every step:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
    var rcWizardDirective = {
     'rcWizard': function () {
       return {
         restrict: 'A',
         controller: ['$scope', function ($scope) {
 
           var self;
           var wizardElement;
           var wizardOptions = {};
           var steps = []; 
           this.currentIndex = 0;
           this.firstIndex = 0;
           this.navigationLength = 0;
 
           this.addStep = function (step) {              steps.push(step);              if (!step.element || !step.submitController) return;              // if a rcSubmitController is being used, automatically add a _hidden_              // submit button so that               // in order to place an submit button that is still functional it              // has to technically be visible, so instead when place it way off              // screen             jQuery(step.element)               .append('<input type="submit" tabindex="-1"' +                       'style="position: absolute; left: -9999px; width: 1px; height: 1px;" />')               .attr('action', 'javascript:void(0);');              // bind to the submit complete event on the rcSubmitController and              // if the action was successful, trigger a next on the wizard.             step.submitController.onSubmitComplete(function (evt) {               if (evt.success) {                 self.onForward(step);               }             });           };
 
           this.forward = function () {
              var currentStep = (steps.length > self.currentIndex) ?                                steps[self.currentIndex] : null;              if (!currentStep) return;              if (currentStep.submitController) {               currentStep.submitController.submit();             } else {               self.onForward(currentStep);
             }
           };            var onForward = function(currentStep) {              if (currentStep.formController && currentStep.formController.$invalid) return; 
             wizardElement.bootstrapWizard('next');
           };

The addStep method takes in a ‘step‘ object that has useful information such as the step‘s element and its rcSubmit controller if it has one. Using this information we can tap into that step‘s submit logic using onSubmitComplete. Using that, we can now base moving forward in the wizard on the successful completion of a form submission. We can also do some other nifty things to make a better user experience. For instance, if these steps are represented by forms, when can automatically add a hidden submit input so that submit-on-enter behavior works. You’ll note this code is designed to work with or without the rcSubmit controller. We try not to require additional modules unless their functionality is being used.

The rcWizard controller now has methods to properly track our enhanced steps. Next we need code that actually adds the steps to the rcWizard‘s controller. This will involve another new directive, ‘rcStep‘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    var rcWizardStepDirective = {
      'rcStep': function () {
        return {
          restrict: 'A',
          require: ['^rcWizard', '?form', '?rcSubmit'],
          link: function (scope, element, attributes, controllers) {
 
            var wizardController = controllers[0];
 
            // find all the optional controllers for the step
            var formController = controllers.length > 1 ? controllers[1] : null;
            var submitController = controllers.length > 2 ? controllers[2] : null;
 
            // add the step to the wizard controller
            var step = wizardController.addStep({ 
              'element': element, 
              'attributes': attributes, 
              'formController': formController,
              'submitController': submitController });
          }
        };
      }
    };

This directive is simple enough. It merely calls the addStep method on the rcWizard controller including the element, and the optional ngFormController and rcSubmit controller. These are optional because they are not always necessary for a basic wizard to function.

That’s enough javascript coding. We now need to update the markup to take advantage of our new functionality:

1
2
3
4
5
6
7
8
    <div ng-app="SampleWizardApp" ng-controller="SampleWizardController"
         rc-wizard="sampleWizard">
      <ul class="nav nav-pills">
        <li class="active">
          <a class="active" href="#first" data-toggle="tab">
            <span>1</span> <span>First Step</span>
          </a>
        </li>

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
      <div class="tab-content">
        <form class="tab-pane active" id="first" name="firstForm" novalidate rc-submit rc-step>
          <h2>Enter first step data</h2>
          <div class="form-group">
            <label class="control-label">First Name</label>
            <input name="firstName" class="form-control" type="text" 
              ng-model="user.firstName" required />
          </div>
          <div class="form-group">
            <label class="control-label">Last Name</label>
            <input name="lastName" class="form-control" type="text" 
              ng-model="user.lastName" required />
          </div>
        </form>
        <form class="tab-pane" id="second" name="secondForm" novalidate rc-submit rc-step>
          <h2>Enter second step data</h2>
          <div class="form-group">
            <label class="control-label">Street Address</label>
            <input name="streetAddress" class="form-control" type="text" 
              ng-model="user.streetAddress" />
          </div>
          <div class="form-group">
            <label class="control-label">City</label>
            <input name="city" class="form-control" type="text" 
              ng-model="user.city" />
          </div>
          <div class="form-group">
            <label class="control-label">State</label>
            <input name="state" class="form-control" type="text" 
              ng-model="user.state" />
          </div>
          <div class="form-group">
            <label class="control-label">City</label>
            <input name="postalCode" class="form-control" type="text" 
              ng-model="user.postalCode" />
          </div>
        </form>
        <form class="tab-pane" id="last" name="lastForm" novalidate rc-submit rc-step>
          <h2>Finish last step</h2>
          <div class="form-group">
            <label class="control-label">First Name:</label>
            <p class="form-control-static">{{ user.firstName }}</p>
          </div>
          <div class="form-group">
            <label class="control-label">Last Name:</label>
            <p class="form-control-static">{{ user.lastName }}</p>
          </div>
          <div class="form-group">
            <label class="control-label">Address:</label>
            <p class="form-control-static">
              {{ user.streetAddress }}
              <br />
              {{ user.city }}, {{ user.state }} {{ user.postalCode }}
            </p>
          </div>
        </form>
      </div>

All we did was convert all the tab-pane’s from div elements to form elements. We added our rcSubmit and rcStep directives as well. Now each step functions as its own validating form. In the first step we added some required attributes. Now if we attempt to continue to the next step it will not let us move forward until we fill out those fields.

This is all great and does exactly what we want to do. But since we are building based on some pretty cool directives, we can easily add some very helpful features. First, we can use our submission attempt tracking from this blog to highlight error’d fields when the user attempts to move forward too soon. Second, if we have a service call between steps that we need to wait for before moving forward and we want to disable the UI while we do so, we have rcDisabled from this blog. Using all these together we along with a little custom styling (i.e the rc-nav-wizard CSS class), we have an uber-wizard:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
   <div ng-controller="SampleWizardController" 
        rc-wizard="sampleWizard" rc-disabled="rc.firstForm.submitInProgress">
     <ul class="nav rc-nav-wizard">
       <li class="active">
         <a class="active" href="#first" data-toggle="tab">
           <span class="badge">1</span>
           <span>First Step</span>
         </a>
       </li>
       <li>
         <a href="#second" data-toggle="tab">
           <span class="badge">2</span>
           <span>Second Step</span>
         </a>
       </li>
       <li>
         <a href="#last" data-toggle="tab">
           <span class="badge">3</span>
           <span>Last Step</span>
         </a>
       </li>
     </ul>
     <div class="tab-content">
       <form class="tab-pane active" id="first" name="firstForm" 
             rc-submit="saveState()" rc-step novalidate>
         <h2>Enter first step data</h2>
         <div class="form-group"
              ng-class="{'has-error': rc.firstForm.needsAttention(firstForm.firstName)}">
           <label class="control-label">First Name</label>
           <input name="firstName" class="form-control" type="text" required
                  ng-model="user.firstName"/>
         </div>
         <div class="form-group"
              ng-class="{'has-error': rc.firstForm.needsAttention(firstForm.lastName)}">
           <label class="control-label">Last Name</label>
           <input name="lastName" class="form-control" type="text" required
                  ng-model="user.lastName" />
         </div>
       </form>

And there you have it. A nice little wizard module. This is also a great example of how building modular components can really boost future development. As usual, we’ve made a Plunker and the source and examples are available on our Github. (Please note, all solutions presented in this post are based on AngularJS 1.0.8 and Bootstrap 3.0.0)

AngularJS: Automatically Disable Groups of Elements During HTTP Calls…or Any Call

There are many instances where you need to collect data from a user and post it to a service. AngularJS makes this pretty easy using the $http service. However when you are submitting data, your app is in a sort of suspended state. Because of the issue of confusion and multiple submissions, you don’t want the user to interact with certain elements until the submission is complete. So we created what we think is a relatively simple way to disable/block the UI during form submission. If you are less concerned about the “why” and the “how” and just want to see some code, head on over to our GitHub and look at our rcDisabled module.

When developing directives it is sometimes helpful to begin with how you want that directive to be used. If you just start coding the directive, the resulting implementation can be less intuitive. We want a simple way to disable our UI when a form is submitting. Ideally we want to accomplish that with some simple mark-up like so:

   <form name="loginForm" novalidate="" ng-app="LoginApp" ng-controller="LoginController" 
         rc-submit="login()" rc-disabled="rc.loginForm.submitInProgress">
     <div class="form-group" 
          ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.username)}">
       <input class="form-control" name="username" type="text" 
              placeholder="Username" required="" ng-model="session.username" />
       <span class="help-block" ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group" 
          ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.password)}">
       <input class="form-control" name="password" type="password" 
              placeholder="Password" required="" ng-model="session.password" />
       <span class="help-block" ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
       <a class="btn btn-primary pull-right">
         Link Action
       </a>
       <span class="pull-right">&nbsp;</span>
       <button type="submit" class="btn btn-primary pull-right" value="Login" title="Login">
         <span>Login</span>
       </button>
     </div>
   </form>

Add here is how we get there…

In one of our earlier posts we explored advanced AngularJS form validation, using a simple login form. This post builds on that. On a login form (or any data entry form for that matter), you usually submit data to a service and wait for a response. Some people handle this by creating a busy flag and manipulating styles or the DOM to disable the interface until a result is returned. We saw two separate problems here: One, we wanted an intuitive way to easily provide this busy state information on any form we were submitting. And Two, a simple way to disable the interface while we were waiting.

The first problem involves tapping into the form submission process. Luckily we already started down this path in our previous blog with the rcSubmit directive. We bind to the form’s submit event then execute the specified method if the form is valid. However this just the beginning of the submit process. If we are calling a service method we need to know when its completed. In AngularJS it is common to use the $http service to call web service methods. This service utilizes promises which can be very useful to us. If we have a promise, we can respond when it is resolved or rejected. At the same time, we don’t want to require the use of promises in every instance. If you don’t need to know when it completes or if your method is synchronous, it still should just work. Bearing all that in mind, here is the resulting rcSubmit directive with our changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
   var rcSubmitDirective = {
     'rcSubmit': ['$parse', '$q', '$timeout', function ($parse, $q, $timeout) {       return {
         restrict: 'A',
         require: ['rcSubmit', '?form'],
         controller: ['$scope', function ($scope) {
 
           var formController = null;
           var submitCompleteHandlers = []; 
           this.attempted = false;
           this.submitInProgress = false; 
           this.setAttempted = function() {
             this.attempted = true;
           };
 
           this.setFormController = function(controller) {          
             formController = controller;
           };
 
           this.needsAttention = function (fieldModelController) {
             if (!formController) return false;
 
             if (fieldModelController) {
               return fieldModelController.$invalid && 
                      (fieldModelController.$dirty || this.attempted);
             } else {
               return formController && formController.$invalid && 
                      (formController.$dirty || this.attempted);
             }
           };
 
           this.onSubmitComplete = function (handler) {              submitCompleteHandlers.push(handler);           }; 
           this.setSubmitComplete = function (success, data) {              angular.forEach(submitCompleteHandlers, function (handler) {               handler({ 'success': success, 'data': data });             });           };         }],
         compile: function(cElement, cAttributes, transclude) {
           return {
             pre: function(scope, formElement, attributes, controllers) {
 
               var submitController = controllers[0];
               var formController = (controllers.length > 1) ? controllers[1] : null;
 
               submitController.setFormController(formController);
 
               scope.rc = scope.rc || {};
               scope.rc[attributes.name] = submitController;
             },
             post: function(scope, formElement, attributes, controllers) {
 
               var submitController = controllers[0];
               var formController = (controllers.length > 1) ? controllers[1] : null;
               var fn = $parse(attributes.rcSubmit);
 
               formElement.bind('submit', function () {
                 submitController.setAttempted();
                 if (!scope.$$phase) scope.$apply();
 
                 if (!formController.$valid) return false;
 
                 var doSubmit = function () {                    submitController.submitInProgress = true;                   if (!scope.$$phase) scope.$apply();                    var returnPromise = $q.when(fn(scope, { $event: event }));                    returnPromise.then(function (result) {                     submitController.submitInProgress = false;                     if (!scope.$$phase) scope.$apply();                     // This is a small hack.  We want the submitInProgress                     // flag to be applied to the scope before we actually                     // raise the submitComplete event. We do that by                     // using angular's $timeout service which even without                     // a timeout value specified will not fire until after                     // the scope is digested.                     $timeout(function() {                       submitController.setSubmitComplete(true, result);                     });                    }, function (error) {                     submitController.submitInProgress = false;                     if (!scope.$$phase) scope.$apply();                     submitController.setSubmitComplete(false, error);                   });                 }; 
                 if (!scope.$$phase) {                   scope.$apply(doSubmit);                 } else {                   doSubmit();                   if (!scope.$$phase) scope.$apply();                 }               });
             }
           };
         }
       };
     }]
   };

Starting in the post method, we have wrapped the result of the rcSubmit method using $q.when which gives us a promise no matter what. This allows us to handle the method the same way in all cases: First we set our state flag, submitInProgress. If it’s just a normal non-promisey method, it will execute and when its completed, we will unset the flag. If the method returns a promise, it will wait for the promise to be resolved/rejected and then unset the flag.

We also added a basic event infrastructure for onSubmitComplete. Although we may not use it in this instance, having a way to handle this event may be useful in the future.

On to our second problem. To accomplish the disabling, we first looked at ngDisabled. However, it is only supported directly on elements that support the disabled attribute (i.e. input and button elements). This is understandable but we needed more. We don’t want to have to repeat the same logic on every input/button on the form. In this instance it’s only a few elements, but it can get a little crazy on a more complex input form. In a perfect world, we want to be able to apply the directive on any element and the directive is smart enough to only apply the disabled attribute on the children that support it. Which brings us to ‘rcDisabled‘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   var rcDisabledDirective = {
     'rcDisabled': function () {
       return {
         restrict: 'A',
         link: function (scope, element, attributes) {
 
           scope.$watch(attributes.rcDisabled, function(isDisabled) {
             var jqElement = jQuery(rootElement);
 
             return jqElement
                      .find(':not([rc-disabled])')
                      .filter(function(index) {
                        return jQuery(this)
                                 .parents()
                                 .not(jqElement)
                                 .filter('[rc-disabled]').length === 0;
                      })
                     .filter('input:not([ng-disabled]), button:not([ng-disabled])')
                     .prop('disabled', isDisabled);
           });
         }
       }
     }
   };

Great! It does exactly what we wanted: added/removed the disabled attribute from all supported child elements. We even cleverly ignore sub items that are using their own rcDisabled or ngDisabled directive. This allows for more complex scenarios where nested disabling directives might have different logic. Also, you may notice the explicit use of jQuery. AngularJS includes a minimal version of jqLite, however we are using some methods (namely ‘filter‘ and ‘not‘) that are only available in the full version of jQuery. So when using this directive we have to recognize that jQuery is a dependency. Although we still require even more functionality. We here at RealCrowd also use Twitter Bootstrap (which is awesome by the way). And Bootstrap gives us the ability for links/anchors (‘<a>‘) to look and behave like buttons. However links do not support a disabled attribute. Bootstrap was smart about this and added a .disabled CSS class. We could modify our directive to take this into account, but we try to design our directives to be implementation-agnostic when possible. Instead of putting Bootstrap-specific logic in the directive, we want it to be configurable. In AngularJS, when you want something to be configurable, you can use a provider. We therefore created a rcDisabledProvider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   var rcDisabledProvider = function () {
 
     var defaultDisableHandler = function(rootElement, isDisabled) {
       var jqElement = jQuery(rootElement);
 
       return jqElement
               .find(':not([rc-disabled])')
               .filter(function(index) {
                 return jQuery(this)
                          .parents()
                          .not(jqElement)
                          .filter('[rc-disabled]').length === 0;
               })
               .filter('input:not([ng-disabled]), button:not([ng-disabled])')
               .prop('disabled', isDisabled);
     };
 
     var customDisableHandler;
 
     this.onDisable = function (customHandler) {
       customDisableHandler = customHandler;
     };
 
     this.$get = function () {
       return {
         disable: function (rootElement, isDisabled) {
           return (customDisableHandler) ? 
                  customDisableHandler(rootElement, isDisabled) : 
                  defaultDisableHandler(rootElement, isDisabled);
         }
       }
     };
   };

For those of you unfamiliar with providers, simply view them as a configurable service with state. In AngularJS you can configure a provider for a module/application and use it in any controllers or directives you want just as you would a service. The methods used for configuring are defined in the root provider function. In this case we have one such method called onDisabled. The actual rcDisabled service instance is defined by the special $get method. For the rcDisabledProvider, the common state is our method for disabling/re-enabling DOM objects. We have a default method that is the same logic as our original rcDisabled directive. However, we also have the option to configure the provider with a custom method using onDisabled. We now need to update the rcDisabled directive to use the rcDisabledProvider:

1
2
3
4
5
6
7
8
9
10
11
12
13
   var rcDisabledDirective = {
     'rcDisabled': ['rcDisabled', function (rcDisabled) {
       return {
         restrict: 'A',
         link: function (scope, element, attributes) {
 
           scope.$watch(attributes.rcDisabled, function(isDisabled) {
             rcDisabled.disable(element, isDisabled);           });
         }
       }
     }]
   };

A quick note on the above code. You’ll notice that the included dependency for the rcDisabledProvider just says ‘rcDisabled‘. The way providers work in AngularJS is they are defined without a ‘Provider‘ suffix just as you would a service. The only time the suffix is used is when you configure it (which we will show below). This may also cause confusion as the directive is also called ‘rcDisabled‘. This doesn’t cause any conflicts in Angular that I’m aware, but admittedly this may not be the best design. I have personally justified it thinking that confusion should not occur often in the actual use of this directive and provider. You will either be placing and rc-disabled attribute on an element or configuring this rcDisabledProvider in the application or module. Hopefully that clears things up.

The directive will now use either the default method or whatever custom method has been defined. If you were to use a custom method as we wish to do for our Bootstrap implementation, you would configure it like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   angular.module('rcDisabledBootstrap', ['rcDisabled'])
   .config(['rcDisabledProvider', function(rcDisabledProvider) {
     rcDisabledProvider.onDisable(function(rootElement, isDisabled) {
       var jqElement = jQuery(rootElement);
 
       return jqElement
               .find(':not([rc-disabled])')
               .filter(function(index) {
                 return jQuery(this)
                          .parents()
                          .not(jElement)
                          .filter('[rc-disabled]').length === 0;
               })
               .filter('input:not([ng-disabled]), button:not([ng-disabled]), .btn, li')
               .add(jqElement)
               .toggleClass('disabled', isDisabled)
               .filter('input, button')
               .prop('disabled', isDisabled);
     });
   }]);

The above code creates an augmented module called ‘rcDisabledBootstrap‘ which just takes in our rcDisabled module and configures it using the rcDisabledProvider. Now our custom method not only toggles the supported disabled attributes, but also toggles the CSS disabled class on appropriate elements. The logic we used to set the disabled class was based on how and where we saw it used in the bootstrap.css file. With this code, we can apply this directive to the following markup:

   <form name="loginForm" novalidate="" ng-app="LoginApp" ng-controller="LoginController" 
         rc-submit="login()" rc-disabled="rc.loginForm.submitInProgress">
     <div class="form-group" 
          ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.username)}">
       <input class="form-control" name="username" type="text" 
              placeholder="Username" required="" ng-model="session.username" />
       <span class="help-block" ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group" 
          ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.password)}">
       <input class="form-control" name="password" type="password" 
              placeholder="Password" required="" ng-model="session.password" />
       <span class="help-block" ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
       <a class="btn btn-primary pull-right">
         Link Action
       </a>
       <span class="pull-right">&nbsp;</span>
       <button type="submit" class="btn btn-primary pull-right" value="Login" title="Login">
         <span>Login</span>
       </button>
     </div>
   </form>

This is a relatively simplified example. You may want to change the UI a bit more to better inform the user what is happening. But one of the great things about this directive is that its easily customizable. If you want to do additional DOM manipulation, you can add whatever you want in the configuration. And there you have it; a nice simple group disabler. We have created a Plunker to show this in action and as always the code and examples are available on our GitHub. (Please note, all solutions presented in this post are based on AngularJS 1.0.8 and Bootstrap 3.0.0)

Bonus

If using Bootstrap, you have the additional option of using some of their custom jQuery plug-ins. One of those is the “Button” plug-in which has some functionality that works nicely with the rcDisabled module. Specifically, it is stateful and allows you to define a data-loading-text attribute on your button. Then, using the plug-in, you can toggle the text when the UI is busy. We can make a slight modification to our Bootstrap version of the module and add our attribute to the markup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   angular.module('rcDisabledBootstrap', ['rcDisabled'])
   .config(['rcDisabledProvider', function(rcDisabledProvider) {
     rcDisabledProvider.onDisable(function(rootElement, isDisabled) {
       var jqElement = jQuery(rootElement);
 
       jqElement = jqElement
                     .find(':not([rc-disabled])')
                     .filter(function(index) {
                       return jQuery(this)
                                .parents()
                                .not(jqElement)
                                .filter('[rc-disabled]').length === 0;
                     })
                     .filter('input:not([ng-disabled]), button:not([ng-disabled]), .btn, li')
                     .add(jqElement);
 
       // if the Bootstrap "Button" jQuery plug-in is loaded, use it on those       // that have it configured       if (jqElement.button) {         jqElement.find('[data-loading-text]').button((isDisabled) ? 'loading' : 'reset');       } 
       jqElement.toggleClass('disabled', isDisabled)
       .filter('input, button')
       .prop('disabled', isDisabled);
     });
   }]);

16
17
18
19
20
21
22
23
24
25
26
     <div class="form-group">
       <a class="btn btn-primary pull-right">
         Link Action
       </a>
       <span class="pull-right">&nbsp;</span>
       <button type="submit" class="btn btn-primary pull-right" value="Login" title="Login"
         data-loading-text="Please Wait...">
         <span>Login</span>
       </button>
     </div>
   </form>

Now our button text will automatically change when we are in a busy state. Keep in mind that using this plugin adds the additional dependency of the Bootstrap javascript file. Though we have coded it so the module will still fallback if it isn’t loaded. And there you have a nice little bonus.

P.S. RealCrowd is always hiring. If you like what you see and are interested in a job, contact me or JD.

AngularJS and Password Managers: Can’t we all just get along?

(Note: This article has been updated to use AngularJS 1.0.8 and Bootstrap 3.0.0. If you are using earlier versions the syntax may be slightly different.) We came across an issue using AngularJS with some of the password manager browser plugins (i.e. 1Password, LastPass). For some reason when these plugins tried pre-filling our forms, the AngularJS validation system would not recognize that the input value changed. After much investigation and support requests, one of the vendors figured out the events AngularJS was listening to on the controls for updating the scope were not firing. So we created a new directive to use with our custom rcSubmit directive to solve this. The directive is called ‘rcVerifySet‘. First we had to extend rcSubmit a little:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
   var rcSubmitDirective = {
       'rcSubmit': ['$parse', function ($parse) {
           return {
               restrict: 'A',
               require: ['rcSubmit', '?form'],
               controller: ['$scope', function ($scope) {
 
                   var formController = null;
                   var attemptHandlers = []; 
                   this.attempted = false;
 
                   this.onAttempt = function(handler) {                       attemptHandlers.push(handler);                   }; 
                   this.setAttempted = function() {
                       this.attempted = true;
 
                       angular.forEach(attemptHandlers, function (handler) {                           handler();                       });                   };
 
                   this.setFormController = function(controller) {
                       formController = controller;
                   };
 
                   this.needsAttention = function (fieldModelController) {
                       if (!formController) return false;
 
                       if (fieldModelController) {
                           return fieldModelController.$invalid && 
                             (fieldModelController.$dirty || this.attempted);
                       } else {
                           return formController && formController.$invalid && 
                             (formController.$dirty || this.attempted);
                       }
                   };
               }],
               compile: function(cElement, cAttributes, transclude) {
                   return {
                       pre: function(scope, formElement, attributes, controllers) {
 
                           var submitController = controllers[0];
                           var formController = (controllers.length > 1) ? controllers[1] : null;
 
                           submitController.setFormController(formController);
 
                           scope.rc = scope.rc || {};
                           scope.rc[attributes.name] = submitController;
                       },
                       post: function(scope, formElement, attributes, controllers) {
 
                           var submitController = controllers[0];
                           var formController = (controllers.length > 1) ? controllers[1] : null;
                           var fn = $parse(attributes.rcSubmit);
 
                           formElement.bind('submit', function () {
                               submitController.setAttempted();
                               if (!scope.$$phase) scope.$apply();
 
                               if (!formController.$valid) return false;
 
                               scope.$apply(function() {
                                   fn(scope, {$event:event});
                               });
                           });
                       }
                 };
               }
           };
       }]
   };

All we are doing is creating a method to pass in a handler that we can execute whenever submission is attempted (onAttempt). When the form submission is attempted, any handlers will also be executed. We now need a directive to consume this and do something on the submission attempt. Enter ‘rcVerifySet‘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    var rcVerifySetDirective = {
      'rcVerifySet': function () {
        return {
          restrict: 'A',
          require: ['^rcSubmit', 'ngModel'],
          link: function (scope, element, attributes, controllers) {
            var submitController = controllers[0];
            var modelController = controllers[1];
 
            submitController.onAttempt(function() {
              modelController.$setViewValue(element.val());
            });
          }
        };
      }
    };

All the rcVerifySet directive does is add a handler to the attempt controller. When executed, this allows us to examine elements that are modified outside of angular (i.e. via plugin) to make sure they are applied to the scope before they are submitted. The resulting html would be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <form name="loginForm" novalidate
          ng-app="LoginApp" ng-controller="LoginController" rc-submit="login()">
        <div class="form-group"
            ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.username)}">
            <input class="form-control" name="username" type="text" placeholder="Username" 
                   required ng-model="session.username" rc-verify-set />  
            <span class="help-block" 
                  ng-show="loginForm.username.$error.required">Required</span>
        </div>
        <div class="form-group"
            ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.password)}">
            <input class="form-control" name="password" type="password" placeholder="Password"
                   required ng-model="session.password" rc-verify-set />
            <span class="help-block"
                  ng-show="loginForm.password.$error.required">Required</span>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary" value="Login" title="Login">
                <span>Login</span>
            </button>
        </div>
    </form>

It should be noted that there is an issue logged for this in AngularJS: https://github.com/angular/angular.js/issues/3133. It appears 1Password is implementing a fix for this issue based on some of our feedback. We have also notified LastPass, but have not heard a response yet (Update: LastPass has now also addressed the issue). Either way, the issue may exist with numerous plugins and this directive may be useful to verify the scope in situations where you think plugins are used. For instance, don’t forget register pages and reset-password pages.

We’ve thrown together a Plunker to see things in action. The source to these directives and an example can be found on our Github. You can access all of our custom directives there including a new one we threw together last week to use Mailgun’s cool email address validation service.

Using Mailgun’s email address validation service with AngularJS

(Note: This article has been updated to use AngularJS 1.0.8 and Bootstrap 3.0.0. If you are using earlier versions the syntax may be slightly different.) Email address validation is hard. The RFC’s are complex, implementations of them vary, and regular expressions you find lying around the internet fall short. In fact, don’t tell anyone, but the validation we do on our web site today is not correct by a long shot. But it has decent coverage over the most common address formats that normal people use.

We want people to use our service. So, we make it as easy as possible to sign up. Investors only need to provide an email address and password to get started. We don’t make an investor type either their email address or their password twice. A typical verification email is employed after an investor signs up on the site and it’s very straightforward to reset your password. Of course, we see a > 0 bounce rate on those verification emails. Even the most well intentioned person types things wrong occasionally. The validation service Mailgun announced today should be a step in the right direction, and we’re excited to try it out!

Our web application uses AngularJS on the front end, and we have spent some time tweaking the user experience of its form validation. We’ll certainly be testing out the Mailgun API, so we decided to see how it might fit in with our form UX.

Andy threw together some code loosely based on the Mailgun jQuery example project. If you’re eager to get started, have a look over on our Github or play around with the Plunker.

The tricky part about a validation system such as this is that it is asynchronous by necessity as you are calling a remote service. You need to provide status to the user, or confusion will ensue. We disable the default form validation, and use the AngularJS system instead.

In order to work around the asynchronous problem we set both an “in progress” and “is valid” validation flag on the model and adjust the UI accordingly. Rather than re-create the functionality, we use the Mailgun jQuery library as-is. We simply wrap the callbacks to modify the state of our AngularJS form validators. Angular magic takes over from there, and the form’s $valid flag remains false until both the call to Mailgun is complete and the email address is valid. The user also sees status updates as to what is going on.

Use the directive by adding a rc-mailgun-valid attribute to your email input.

   <input class="form-control" name="email" type="text" placeholder="Email" 
          ng-model="session.email" rc-mailgun-valid />

We control the messaging to the user by simply using the ng-show directive to display different html based on the progress of the transaction. Did the user enter anything? Is the address valid? Are we in progress validating the address? Was there an error?

   <span class="help-block">
     <span ng-show="loginForm.email.$error.required">Required</span>
     <span ng-show="loginForm.email.$error.rcMailgunEmailValid"> Invalid Email Address</span>
     <span ng-show="loginForm.email.$error.rcMailgunInProgress"> Validating Email Address</span>
     <span ng-show="rcMailgun.mailgunStatus"> Validation Error: {{ rcMailgun.mailgunStatus }}</span>
   </span>

And, finally, disable the submit button until the form is valid, which includes waiting for the call to the Mailgun validation service to complete.

   <button type="submit" class="btn btn-primary" value="Login" title="Login" 
           ng-disabled="!loginForm.$valid">
     <span>Login</span>
   </button>

And there you have it. A much-more-accurate email address validation system, able to be applied to your AngularJS powered form by just adding a couple directives. For a better UX, tie this in with rc-submit and rc-attempt as described in our last dissertation on AngularJS form validation.

Available on Github

Play with it on Plunker

On the Bleeding Edge: Advanced AngularJS Form Validation

(Note: This article has been updated to use AngularJS 1.0.8 and Bootstrap 3.0.0. If you are using earlier versions the syntax may be slightly different.) We’ve been using AngularJS for the past few months and in general it has been really great. There has definitely been a learning curve, but the best part of the design is that it really encourages you to extend it properly. Whenever you try to hack something, it just feels wrong and you are forced to look at your problem from a different perspective. The benefit is the resulting solution is usually much more modular and portable.

I have had several occasions where I’ve had to write my own directives, providers, filters, etc.

Advanced Form Validation

One of the cool features of angular is the form validation. By decorating your field elements with the correct attributes, angular validation will occur automatically and let you know when a field (and in turn the form) is valid or invalid. In addition you can use some conditional css classes to highlight invalid fields to the user. Below is a simple example of a login form, where we keep the “Login” button (i.e. “call to action”) disabled until the form is valid:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
   <form name="loginForm" novalidate 
     ng-app="LoginApp" ng-controller="LoginController" ng-submit="login()">
     <div class="form-group">
       <input class="form-control" name="username" type="text" 
         placeholder="Username" required ng-model="session.username" />
       <span class="help-block" 
         ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group">
       <input class="form-control" name="password" type="password" 
         placeholder="Password" required ng-model="session.password" />
       <span class="help-block" 
         ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
         <button type="submit" class="btn btn-primary pull-right" 
           value="Login" title="Login" ng-disabled="!loginForm.$valid">
           <span>Login</span>
         </button>
     </div>
   </form>

Result:

The above example is functional and works fine. But in reality, its not the greatest user experience. Disabling a call to action like “Login” without a clear reason why can be confusing to the user, even in this simple example of required fields. So using AngularJS (and Bootstrap for easy styling) you can better highlight the fields that need attention:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   <form name="loginForm" novalidate 
     ng-app="LoginApp" ng-controller="LoginController" ng-submit="login()">
     <div class="form-group"
       ng-class="{'has-error': loginForm.username.$invalid}">
       <input class="form-control" name="username" type="text" 
         placeholder="Username" required ng-model="session.username" />
       <span class="help-block" 
         ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group"
       ng-class="{'has-error': loginForm.password.$invalid}">
       <input class="form-control" name="password" type="password" 
         placeholder="Password" required ng-model="session.password" />
       <span class="help-block" 
         ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
         <button type="submit" class="btn btn-primary pull-right" 
           value="Login" title="Login" ng-disabled="!loginForm.$valid">
           <span>Login</span>
         </button>
     </div>
   </form>

Result:

So now our controls are conditionally decorated with an ‘has-error‘ css class if they are currently invalid courtesy of the ‘ng-class‘ directive. But things still aren’t great. We still have a disabled call to action and even though we are highlighting the invalid fields, we are doing so right away. Before the user has done anything we are saying “You’ve done something wrong”. The solution for me was some custom directives. Let’s take a look at the disabled call to action first.

The reason we use the ‘ng-disabled‘ directive to disable the call to action is to prevent the form from being submitted when we know it to be invalid. We could remove the ‘novalidate‘ attribute on the form which will allow the built in browser validation to stop submission based on the ‘required‘ attribute, however there are several other non-standard html5 attributes we could potentially use to validate the field and the built-in browser validation would ignore those. So we basically want to allow for a submission to be attempted via the button click, but cancel it if the form is invalid. Enter ‘rcSubmit‘: (Note: all of our custom directives begin with our own prefix/namespace “rc”, for “RealCrowd”, to avoid any conflicts with other directives we may import)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    var rcSubmitDirective = {
        'rcSubmit': ['$parse', function ($parse) {
            return {
                restrict: 'A',
                require: 'form',
                link: function (scope, formElement, attributes, formController) {
 
                    var fn = $parse(attributes.rcSubmit);
 
                    formElement.bind('submit', function (event) {
                        // if form is not valid cancel it.
                        if (!formController.$valid) return false;
 
                        scope.$apply(function() {
                            fn(scope, {$event:event});
                        });
                    });
                }
            };
        }]
    };

As you can see the directive is pretty simple. It binds to the form’s submit event, and if the ngFormController is not valid, cancels the event. Otherwise it will execute the defined expression. This is basically a copy of the angular ngSubmit with the addition of a validation check. So we just replace the ‘ng-submit‘ attribute with the ‘rc-submit‘ and now we can remove the ‘ng-disabled‘ attribute from our login button because now the submit will not execute if the form is invalid.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   <form name="loginForm" novalidate 
     ng-app="LoginApp" ng-controller="LoginController" rc-submit="login()">
     <div class="form-group"
       ng-class="{'has-error': loginForm.username.$invalid}">
       <input class="form-control" name="username" type="text" 
         placeholder="Username" required ng-model="session.username" />
       <span class="help-block" 
         ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group"
       ng-class="{'has-error': loginForm.password.$invalid}">
       <input class="form-control" name="password" type="password" 
         placeholder="Password" required ng-model="session.password" />
       <span class="help-block" 
         ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
         <button type="submit" class="btn btn-primary pull-right" 
           value="Login" title="Login">
           <span>Login</span>
         </button>
     </div>
   </form>

Okay, so not much changed there really. The disabled call to action though always bugs me. And once we solve our second problem, it will show off its usefulness a bit more. The next problem is we are highlighting invalid fields before the user has done anything which could be a bit confusing. Ideally we should only highlight the fields if the user has interacted with the form. AngularJS has some built-in support for this as well. On the ngFormController there is a $dirty property and $pristine (basically the opposite of $dirty) property. So we can add that as an additional condition on our ‘error‘ css class. Something like:

ng-class="{'has-error': loginForm.username.$invalid && loginForm.username.$dirty}"

But this still isn’t exactly what we want. The field will get highlighted after it’s dirty (i.e. the user has interacted with it), but what if we attempt submission? Technically the form isn’t dirty so the field won’t be highlighted. We need to track another state of the form which isn’t currently being tracked: attempted submission. In the ideal scenario, erroneous fields should only be highlighted if the user has tried to interact with the field or if the user has attempted to submit the form. First, lets track attempted. We could try to expand on the current custom rcSubmit directive, but I can foresee using this directive independent of it at some point so I’m going to make a separate directive, ‘rcAttempt‘:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    var rcAttemptDirective = {
        'rcAttempt': function () {
            return {
                restrict: 'A',
                controller: ['$scope', function ($scope) {
                    this.attempted = false;
 
                    this.setAttempted = function() {
                        this.attempted = true;
                    };
                }],
                link: function(scope, formElement, attributes, attemptController) {
                    formElement.bind('submit', function (event) {
                        attemptController.setAttempted();
                        if (!scope.$$phase) scope.$apply();
                    });
                }
            };
        }
    };

In the code above you can see we create a custom controller with a property to track if form submission has been attempted. Then, like our rcSubmit, we bind to the form’s submit event, and set the ‘attempted‘ flag there. We can add this directive to our form element, but it won’t really do anything at this point. We are only tracking the state, but are not doing anything with it. We need a way access this information in the markup just like other form properties. The way to do that is by putting our new controller on the scope:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    var rcAttemptDirective = {
        'rcAttempt': function () {
            return {
                restrict: 'A',
                controller: ['$scope', function ($scope) {
                    this.attempted = false;
 
                    this.setAttempted = function() {
                        this.attempted = true;
                    };
                }],
                compile: function(cElement, cAttributes, transclude) {                    return {                        pre: function(scope, formElement, attributes, attemptController) {                            scope.rc = scope.rc || {};                            scope.rc[attributes.name] = attemptController;                        },                        post: function(scope, formElement, attributes, attemptController) {                            formElement.bind('submit', function (event) {                                attemptController.setAttempted();                                if (!scope.$$phase) scope.$apply();                            });                        }                    };                }            };
        }
    };

We use the ‘compile‘ function to manipulate the scope just as we would if we manipulate the DOM on ‘compile‘. We add an ‘rc‘ object, again to avoid conflicts with other scope values then, mimicking the ngFormController, use the form name. So when we access it in the markup it will look like: ‘rc.loginForm‘. We also move the binding to the post-linking function of ‘compile‘ because if you have a ‘compile‘ defined, the ‘link‘ function with be ignored. So now that the hard work is done we just need to add the directive and change our ‘ng-class‘ to use the new attempted state we are tracking:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   <form name="loginForm" novalidate 
     ng-app="LoginApp" ng-controller="LoginController" 
     rc-attempt rc-submit="login()">
     <div class="form-group" 
       ng-class="{'has-error': loginForm.username.$invalid && 
         (loginForm.username.$dirty || rc.loginForm.attempted)}">
       <input class="form-control" name="username" type="text" 
         placeholder="Username" required ng-model="session.username" />
       <span class="help-block" 
         ng-show="loginForm.username.$error.required">Required</span>
     </div>
     <div class="form-group" 
       ng-class="{'has-error': loginForm.password.$invalid &&
         (loginForm.password.$dirty || rc.loginForm.attempted)}">
       <input class="form-control" name="password" type="password" 
         placeholder="Password" required ng-model="session.password" />
       <span class="help-block" 
         ng-show="loginForm.password.$error.required">Required</span>
     </div>
     <div class="form-group">
         <button type="submit" class="btn btn-primary pull-right" 
           value="Login" title="Login">
           <span>Login</span>
         </button>
     </div>
   </form>

Success! So now if we open the page fresh, the form is clean. If the user manipulates a particular field and leaves it invalid, only that particular field will be highlighted. If the user attempts to submit the form, all invalid fields will be highlighted. Here is a link to the Plunker to see it in action: View Plunker.

Custom directives in AngularJS can be very powerful, and the design of AngularJS encourages building modular components. You can see this in production on all of our forms, such as the Register form.

Note: The source for all the directives and examples can be found on our public GitHub repo: https://github.com/realcrowd/angularjs-utilities

Quick Update: Refinement and Bonus Method. As with most code, we have refined and enhanced as we’ve moved forward. Here are a couple small changes we’ve made since writing this blog. First, the separation of rcAttempt and rcSubmit ended up being unduly complex for our needs. We therefore moved the functionality in rcAttempt into rcSubmit so we now just need one directive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    var rcSubmitDirective = {        'rcSubmit': function () {            return {                restrict: 'A',                require: ['rcSubmit', '?form'],                controller: ['$scope', function ($scope) {                    this.attempted = false;                     this.setAttempted = function() {                        this.attempted = true;                    };                }],                compile: function(cElement, cAttributes, transclude) {                    return {                        pre: function(scope, formElement, attributes, controllers) {                             var submitController = controllers[0];                             scope.rc = scope.rc || {};                            scope.rc[attributes.name] = submitController;                        },                        post: function(scope, formElement, attributes, controllers) {                             var submitController = controllers[0];                            var formController = (controllers.length > 1) ?                                                  controllers[1] : null;                             var fn = $parse(attributes.rcSubmit);                             formElement.bind('submit', function (event) {                                submitController.setAttempted();                                if (!scope.$$phase) scope.$apply();                                 if (!formController.$valid) return false;                                 scope.$apply(function() {                                    fn(scope, {$event:event});                                });                            });                        }                    };                }            };        }    };

We now no longer need the rc-attempt attribute in our mark-up. Second, we noticed repetitive pattern in our class logic and decided to make a small utility method on our rcSubmitController (formly rcAttemptController) to make the markup a little cleaner. That method needs some additional information to, so we’ll need the following changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    var rcSubmitDirective = {
        'rcSubmit': function () {
            return {
                restrict: 'A',
                require: ['rcSubmit', '?form'],
                controller: ['$scope', function ($scope) {
                    var formController = null;                     this.setFormController = function(controller) {                        formController = controller;                    };                     this.needsAttention = function (fieldModelController) {                        if (!formController) return false;                         if (fieldModelController) {                            return fieldModelController.$invalid &&                                    (fieldModelController.$dirty || this.attempted);                        } else {                            return formController && formController.$invalid &&                                   (formController.$dirty || this.attempted);                        }                    };

30
31
32
33
34
35
36
37
38
39
40
41
42
                compile: function(cElement, cAttributes, transclude) {
                    return {
                        pre: function(scope, formElement, attributes, controllers) {
 
                            var submitController = controllers[0];
 
                            var formController = (controllers.length > 1) ?                                                  controllers[1] : null;                            submitController.setFormController(formController); 
                            scope.rc = scope.rc || {};
                            scope.rc[attributes.name] = submitController;
                        },

In order for our utility method to work, we needed a reference to the ngFormController. Then our method accepts a ngModelController for a field and we do our logic. So now our class logic can be written as:

ng-class="{'has-error': rc.loginForm.needsAttention(loginForm.username)}

Just a couple small little bonuses to keep your code looking clean. The examples and code have been updated on Plunker and GitHub