Saturday, February 8, 2014

Adventures in Angular Directives

If you’re reading this you probably know that “directives” are the Angular glue that binds the browser DOM to your JavaScript. Familiar examples include “ngModel”, “ngBind”, and “ngRepeat”.

Angular ships with a lot of glue but the team can’t cover every possible scenario and they don’t want to try. They expect us, the authors of Angular apps, to extend Angular with our own custom directives.

There’s a lot of great online material about directives – how they work and how to write them. People obsess so much about them that you’d be forgiven for thinking that Angular is all about  writing your own directives.

Please don’t think that! You can go miles and miles without ever writing a single directive. There’s an excellent chance someone has already written the directive you need; search the web first.

Angular is simple and easy to use. We seem to be doing our best to make it look difficult by glomming on to its most complex feature. Really people … let’s not scare newcomers away.

I’ve been living this advice for a long time. I think I’m pretty decent with Angular and I’ve managed to avoid writing custom directives for the most part. Those that I did write were dead simple and not worth crowing about.

I finally stumbled into the need to go beyond rudimentary directive construction with the Breeze “zValidation” directive. This directive taps into an entity’s validation errors collection and, if there are validation errors, will display them on screen in a red box next to the errant property. If the property is required it also displays a required indicator.

Folks like it but they want richer display options. For example, they’d like the directive to display a label for the property in a well-defined location and change the label’s styling when the property is required.

You couldn’t do that with my first version of this directive (which was already the hardest directive I’d ever attempted). I felt it was time to use the dreaded Angular transclusion.

Hard to believe that transclusion is a real word but it is … at least it is in our strange technology world. Ted Nelson coined it in 1963.

Unfortunately, transclusion didn’t work the way I expected. I described my issue on Google Groups under the title “Can't Transclude an Input Element”. This lead to a series of helpful exchanges with the Angular community that resulted in a plunker code sample  that describes a path to a solution. I’ll soon rewrite “zValidate” to take advantage of what I learned.

Meanwhile, I offer my lessons learned by reproducing below the plunker’s readme.md file that provides the details of the journey and its resolution.


You Can't Transclude an Input Element

An attribute directive that will transclude a <div> won't transclude an <input> element as seen in my original plunker.

I can transclude a <div> or <span> that contains an <input> but not the bare <input> itself.

Explanation

I learned from the community that I was mistaken about how transclusion works. Transclusion copies the contents of the container element, not the element itself.

My mental model had been that of ngRepeat in which the element that carries that attribute is included in the repeated (and transcluded) material.

That isn't how it works when we apply transclusion in our own directives. For us the element carrying the directive attribute isexcluded.

Solutions

A series of plunkers from the community made all of this clear. Alternative approaches involved a transclusion function; see this one from Umi and this one from Sander.

Even these were overkill for this particular example because we weren't asking Angular to do anything with the material in the template. Under such hothouse circumstances, there is no need for transclusion either ... just some simple template manipulation as seen in this plunker from me.

However, my goal isn't really that simple. My goal is to enable wrapping an input control in more complex HTML that can display validation error messages, required indicators, and labels. In all such decorations we would ask Angular to fill-in-the-blanks withdata bound to the scope.

The "ultimate solution"?

Ok ... nothing is ever final. But this one demonstrates the essential mechanics for what I want to do.

It employs a compile phase to compose the template around the target element. This happens before there is a scope so it can't do any data binding. The advantage of performing this work in the compile phase before binding data values is that we only perform it once within an ng-repeat block, a fact demonstrated in the this example in the last textbox. Getting these template manipulations out of the way early might improve performance when displaying a long list.

The compile function returns a link function which Angular calls for each data bound scope. This is when Angular fills-in-the-blanks with actual values for each scope instance as illustrated in the textbox within the ngRepeat.

You can manipulate the output HTML in the link phase as well, as seen here:

element.find('mark').text(linkCounter)

where the contents of a <mark> tag is filled by the local value of the linkCounter.

This example directive also demonstrates the utility (and occasional necessity) of a local child scope, enabled by thescope: true setting.

Without that setting, the counter would become a property of the outer scope. We want this counter to update for each binding. If it were not a child scope the link function would increment the one-and-only counter property and we'd see that same value in all of the bindings. Perhaps as bad, we risk overwriting a property of the outer scope called "counter" that we had no business touching. Comment out the scope setting to see what I mean.

Note that we must use the child scope, not the isolate scope. The templated element will surely bind to a value in the outer scope (e.g., the textbox value); an "isolate scope" would shield that value, resulting in an empty binding. Replace the scope setting with scope: {} to see what I mean.

Todo

Of course this isn't the "ultimate solution". I wouldn't bake the template into the directive. I'd want it to be configurable perhaps with a template function option. I'd probably want the developer to be able to set a default template during the Angular "config" phase.

These thoughts are "out of scope" (yuck yuck) for the issued addressed in this example.

Wednesday, January 8, 2014

Song of Myself

With sincere apologies to Walt Whitman, I commend to you an autobiographical sketch recorded with Shawn Wildermuth in late December 2013 as part of his “Hello World” series of developer interviews.
It covers my early years as a Knucklehead Programmer which was kind of like Wolf of Wall Street minus the money, blow, and hookers.
Shawn and I do have a darned good time talking about programming in the 70s/80s (APL, big iron, life before PCs and RDMS), people who changed our lives, and what we can do to nurture the developer community.
Go subscribe to Shawn’s series so you can listen to a great cast of developer characters talk about how they got started in this game.
I wonder if Shawn will interview himself :-)

Extra links

Shawn included a few links on his page but I thought you might like a few more with my memories attached.

Steve Dunwell

Steve Dunwell, the IBM Fellow, lead architect and manager on the pioneering STRETCH computer is remembered in this article, “Return of the prodigal son: the rehabilitation of Steve Dunwell”. His passion for educational computing made my introduction to computing possible at a time when “computers in the schools” was almost inconceivable.  

APL – A Programming Language

APL, my first programming language and my source of income for two decades. Here is Conway’s Game of Life in a single line of “write once, read never” APL: Look Ma! No Loops!
We loved it.  We owned our own 16Kb slice of an IBM/360. No overseers. No types, No compiler. Cult language. We rocked.
My first “computer” was actually an IBM/360 connected by a private telephone line and acoustic coupler to this 2741 terminal, a modified Selectric typewriter.
clip_image001 The Selectric Typewriter printed with a typesphere that rotated and tilted for each letter before striking a ribbon and the paper behind it (see video). IBM made a special typesphere to print those weird APL characters: clip_image002 My first green screen terminal was a 3270 display. It was roughly the size of a foot locker and must have weighed  more than 50 pounds. The manual was over 100 pages. The character set was IBM’s own EBCDIC; ASCII was an option but I don’t remember seeing ASCII actually installed. A bigger, heavier color version arrived with the 3279 some years later:  

History of the Relational Database

I talked some about the early history of the Relational Database when it was fresh and exciting and how it had to overcome the predominate database architectures of its day (architectures we’d now categorize as “NoSQL” ). Did you know that it was invented at IBM by E.F. Codd. and that IBM suppressed it for almost a decade? Read all about it in this fascinating interview with C.J. Date.  It’s a PDF. You’ll learn that Codd wrote an early relational database query language in APL (p.28) and that he hated SQL.  

Community Memory

I talk briefly about my time at Community Memory one of the earliest experiments in social networking. The first Community Memory terminal, at Leopold's Records, Berkeley, CA, 1973. Photo taken by and for the Community Memory Project, first published in the Resource One Newsletter, April 1974, and originally posted to the web in 1996 by Mark Szpakowski The technology was a bunch of teletype terminals in Berkeley laundry mats and record stores, connected by phone lines (no internet). What fascinates me to this day was how CM’s vision of social change through social networking both did and did not happen. You get some sense of that from this BBC article “Hackers and hippies: The origins of social networking” And that’s enough of that!
















Friday, January 3, 2014

Hooray for Durandal (nextGen)

Stop what you’re doing and learn right now about the next generation of Durandal. Watch the video (just 25 minutes) to see how intuitive and easy it is to build a nextGen Durandal application. Then push the “Back This Project” button and help fund it.

Full Disclosure: I have no connection with this project. I just like it a lot. And I put my money where my mouth is.

At IdeaBlade we’ve been big fans of the Durandal presentation framework for building Single Page Applications (SPAs) in HTML and JavaScript. Durandal has served us (and our clients) well for over two years and today’s Durandal deserves its place among the top SPA frameworks. There are lots of ways to learn about it, none better than John Papa’s Pluralsight course, “Single Page Apps JumpStart”.

Durandal’s author is Rob Eisenberg, known to many of you as the man behind the Caliburn.Micro. Rob’s been at this game a long time. I think he must have built and re-built three or four of these presentation frameworks by now, learning and improving with each iteration. He’s didn’t just wake up yesterday and decide he could write a better framework than everyone else. He’s been writing better frameworks than almost everyone else.

I took him very seriously (and got seriously excited) when he told me about the next generation of Durandal for ECMAScript 6 browsers that are just around the corner. I’ve been tracking his new designs and his progress for several months. This next version of Durandal is going to be great.

What’s so great about it? What’s distinctive about it? Rob has his inventory of laudable features (and its impressive). Here are some of the aspects of nextGen Durandal that I love … and that have no equal among alternative frameworks:

  • Convention over configuration – I hate writing and maintaining “switch board” code to connect FooViewModel to FooView and FooRoute etc. I want to say “Foo” and be done with it … until and unless I have a compelling reason to break convention.
  • Customizable conventions – Rob makes good choices but I’m free to define my own.
  • Page life-cycle – Durandal has baked in understanding of the birth and death of “pages” so I don’t have to make up my own hacks to ensure that new pages are initialized on creation and cleaned up on destruction.
  • Asynchrony throughout – Need to wait for the user to confirm or cancel before moving off the page? That’s easy in Durandal because asynchrony is plumbed through the page life-cycle and everywhere else. Dynamically load optional modules on-demand? Easy.
  • Diagnostics – With debug mode turned on the console tells me exactly what choices Durandal is making for me as they happen. I can tap into that logging pipeline with my own diagnostics.
  • Write less, do more – You all know what I mean. We all want to write less code. That’s the motherhood and apple pie that every framework promises. They usually deliver something else. Check out the nextGen Durandal sample video and tell me what other technology is that clear and concise.

Yes, there are other presentation frameworks out there and I like one or two of them as well. Why get involved with the Durandal project, even if it is great? Shouldn’t we just back “the winner”?

I don’t think we can afford to just sit here and let any one of the frameworks dominate. That’s not good for the web. It wasn’t good when IE6 owned the browser world even if it was the best browser at the time. It won’t be good for the web if today’s favorite owns this presentation framework space either. Frankly, no one has nailed it yet. They all make me itch. It’s too early to declare a winner.

We need to encourage real competition … by which I mean truly well done, distinctive approaches to our common application building problems. Durandal is a worthy competitor. It fosters ideas and techniques that must find their way into our application development practices. Durandal deserves your support. Go give it some love.