ProtractorJS is a robust and easy to use e2e test framework specifically designed for testing AngularJS applications. With some simple edits and a slight change in thinking, you can also use it to test your non-angular web apps and provide some sanity to your testing strategy across projects.
ProtactorJS is an end to end test framework from Google used to test AngularJS Apps. While similar to existing tools like CasperJS, ProtractorJS is specifically designed for use with AngularJS.
With minimal effort you can use Protractor with your Vanilla JS web app as well. Why would you do this?
For one, using the same test framework for all you apps provides some sanity to writing tests for all of your projects. And you can’t honestly tell me you have all your apps converted to AngularJS already.
Second, it’s gaining popularity and for good reason. It’s a solid testing framework and is relatively easy to set up. Also, it has the backing of a very well known company (cough cough, Google) so it will be around for a long time.
Finally, it’s use of Jasmine and suite structures allow you to write some flexible tests. Encapsulate your logic, group stuff in ways that make sense. No more fragile tests!
Enough stumping, let’s get to the parts you actually care about.
You can use other frameworks, but my preference is Jasmine.
Selenium Server & Webdriver
Protractor interacts with your tests using Seleniums Server and Webdriver. You can run Selenium locally or use a hosted service like Sauce Labs.
Local installation and setup is turn key simple using NPM.
A Web server
Since your tests use a real browser to execute, you need a host of some kind.
It’s entirely possible to run your tests against an external server (like your staging server), but in practice I like to serve locally. In our example I used the local-web-server NPM package.
Protractor Test Concepts
Again, I’ll point you to the main documentation for longer descriptions of the concepts, I wanted to point out some that need to be discussed when prepping your protractor tests for execution on your VanillaJS app.
A config file sets up some required variables and tells Protractor how to run its tests. This includes a directory where your tests are held, the testing framework you use to write your tests and the address to the selenium server instance you use to run Karma.
Spec File (Test Suite) – “Describe”
Test suites are groups of testing conditions that focus on a particular section or part of your application. Using Jasmine, these are structure with the “describe” function and a brief string indicating the portion of the application under test.
Hooks are small functions that are called during test executions. An example is the beforeEach hook we use to set up our tests for use with non-angular code. See the note below on exactly what goes in this hook.
Test Blocks – “It”
Test blocks are identified by an “it” phrase that describes in simple terms what you expect to happen. This is useful for turning user stories into tests like “User Registration Form should validate user input”.
These test blocks do have some minimal setup but are mostly for performing actions and asserting values. Check out our example code to see some of this in action.
Page Objects are similar to test fixtures in other testing frameworks, but thats underselling the usefulness of this concept. Page Objects are small JS objects where you can encapsulate and abstract out common page elements and share between your tests.
Use these to abstract out some commonly tested things, like getting the text or value from a page element. If you use your page object in all your tests, you only have one place to update when a change is made (instead of having to update ALL your test suites).
Running Protractor on your Vanilla JS App
Like we noted above, Protractor was designed for testing AngularJS apps by default. A large difficulty in e2e web app testing is knowing when something has rendered on the page and is ready to have some interaction. AngularJS abstracts how you work with the DOM in JS as well as having some control over how something is determined to be “ready” using Zones.js.
Three major things need to be done to make sure your Protractor test will actually work with out Angular:
Expose the web driver in a way you can access the DOM for interaction.
Due to the nature of how Angular abstracts the DOM and how it takes over all the app’s event cycles. We need to expose the Selenium Web Driver in a way you won’t hate.
Add this line to your onPrepare hook in the config file to assign the web driver to an global variable called “dv”
global.dv = browser.driver;
Tell the test not to wait for Angular to give the “go ahead, I’m ready” signal.
Protractor uses Angular to tell it when the page under test is ready to be tested. We need to skip this in order to test our non-angular app.
Add this to each test suite’s beforeEach hook to make sure the test knows to run as we expect
dv.ignoreSynchronization = true;
Start thinking about your tests with Promises
While I’m sure most of us at this point have seen and used Promise style functions. When testing an Angular app, using the default locators is easy. Since we are testing our app using the native web driver, we need to use a promise to allow Selenium to return the DOM element itself. Really though, it’s not that tough.
Here is an example where we want to assert the value of an element with the css ID of “foo” using a series of chained promises.
Protractor does indeed have a very basic plugin system that gives end users some ways to extend base functionality. I’m still trying to understand this system myself (I haven’t figured out how to use a plugin that isn’t globally installed) I have found one that is very useful called jasmine2-protractor-utils.
I’ll leave some of the longer explanation of this plugin to the author, but my favorite feature is the ability to take a screenshot of the browser in the test on suite or block failure. Once you get things up and running so your tests are running automatically, having some visual artifacts of a failed test will help you replicate and diagnose what and how things went wrong.
Example – Movie Vote
Here is an example (very small) Web App demonstrating a very basic suite of Protractor tests. You can simply clone this repo, install the required packages using the package.json file and run these tests. Simply follow the instructions in the README.md file.
With any luck you have moved beyond the anti-patterns of yore and you have abstracted your JS functionality into some coherent objects to maintain your sanity. Now it’s time to start testing these pieces of code.
I should note, unlike many other xUnit frameworks, Jasmine is BDD or a Behavior Driven Development framework. This is a fancy way of saying you structure your test suites in a way where you test ‘behavior’ scenarios rather than simple methods and functions.
Karma is a test runner that executes your unit tests in a ‘real browser’. In short, it runs your Jasmine tests in a real browser via websockets.
This means you can test using a headless browser like PhantomJS or a real browser like Chrome. This really becomes useful when you need to test in multiple browsers, but especially useful when you need to run your tests locally (via Chrome) or remotely on a CI (in our examples below we run the unit tests using Chromium. More on that later).
There’s a little setup involved with Karma, but not too much. Honestly, it took less time to get my Karma config created than it did to write my example unit tests.
Travis CI is a hosted continuous integration tool that will watch your repo and execute your tests on certain conditions like a push or a pull request. It is also is free for your open source, or at least your public, Git Hub repos. Best of all, you can also show a super cool ‘build status’ badges in your github readme page.
Travis CI: Using Chromium
Please note that if you run your KarmaJS tests locally using Chrome, you will need to make sure Travis CI knows to use the open source equivalent Chromium as it fit’s into its ‘free tier’ licensing scheme.
Below are the key things you need to set this up, all of this code can be found in our examples below:
We need to tell Travis to install the Chromium browser package when it creates the container. Add the noted entry (‘export CHROME_BIN=chromium-browser’) into the “before_install” section of your travis config.
Next we need to determine if our tests are executed by Travis, and if so, tell Travis to use Chromium (which is aliased to CHROME_BIN from our config above) when exec’ing our tests:
// Config values to allow TravisCI to run chrome in it's container
browsers: ['Chrome', 'ChromeCanary'],
// tell TravisCI to use chromium when testing
// Detect if this is TravisCI running the tests and tell it to use chromium
config.browsers = ['Chrome_travis_ci'];
I think its easiest to look at config from our example code to see exactly where this is placed in your config: https://github.com/arroyolabs-blog/movie-vote/blob/master/karma.conf.js
Testing is a very important part of software development and can be fun and easy once you get things set up to run automatically. Hopefully after reading this post you will have a good idea of how to integrate unit testing into your JS projects.
The Shadow DOM is a way to create elements that are not affected by the same attributes and properties as those in the Light DOM. The Shadow DOM provides true scope encapsulation; your element’s CSS and JS are scoped to it alone! Think of the Shadow DOM as a lightweight version of an iframe.
When you think about creating a web page, we typically think about the HTML elements we structure and style and interactive with using CSS and JS. For the sake of simplicity, we will call the elements you see rendered as the Light DOM.
The Shadow DOM by contrast is a way to create elements that are not affected by the same attributes and properties as those in the Light DOM. The Shadow DOM provides true scope encapsulation; your element’s CSS and JS are scoped to it alone! Think of the Shadow DOM as a lightweight version of an iframe.
To render elements created via the Shadow DOM, you must ‘inject’ them into the Light DOM. We’ll cover some examples of this later in the post.
You have already seen the Shadow DOM
The most common example is the Video Tag. Take this simple example tag:
This simple tag results in the following rendered HTML in your browser:
Notice how much “extra” HTML is rendered under the “#shadow-root”. This code is generated by your browser automatically to give you these complex UI elements like the Play Button and the Volume Slider.
These elements have their own styling and event listeners that are not affected by the host DOM.
Why should we care about the Shadow DOM?
Using the Shadow DOM you can create truly re-usable pieces of code you know will act reliably no matter where you place them. Create one widget, and use it in any of your code, and stop worry about CSS and JS collisions!
Also, most importantly, the Shadow DOM is the base from which the modern web is being built upon.
When we talk about web components, we are talking about the implementation of the Shadow DOM. When you see those fancy ‘live’ updating forms in Angular2, again, Shadow DOM.
Clearly, understanding this is quite important to understanding these new web frameworks.
Example 1: Inserting Elements into a Host Root
Here is a very basic example illustrating using the Shadow DOM to inject elements into a host root.
Example 2: Isolated styles in a Shadow DOM Element
Here is a very basic example showing the isolated CSS styling when using the Shadow DOM.
Please note the injected element’s CSS does not affect the CSS in the host element. Only the injected elements are red.
Example 3: Insertion Points with “content” tags
Here is an example showing insertion points and querying using the content tag. (Please note, that in Shadow DOM v1, the content tag will be replaced by the slot selector, read more about this below in “Whats Next”)
This simple example shows how one can select some content from the host element, inject it into the Shadow DOM template, which in turn get injected into the host DOM.
We reviewed some concepts about the Shadow DOM laid out in what is commonly referred to as “Shadow DOM v0”. This is to say we are working with the very first iteration of the implementation.
The new spec for v1 has, for the most part, been agreed upon and the major browser publishers are working on implementing the new features.
Hayato Ito at Google has a great list explaining some of the changes we can expect along with simple examples showing these new features.
While I provided only simple examples of the Shadow DOM, I hope this inspires you to explore more yourself. Thanks for reading!
How it Works
TypeScript is just a superset of JS that compiles to ES3, ES5 or ES6. Think of this as a higher level language that normalizes the features of ES5 & ES6 into a version compatible with your target language and polyfills missing features.
This means, if you are compiling to ES3, TS will turn your fancy ES6 class into the syntactic sugar required to replicate it in ES3. Also, it will do it better than you.
Why TypeScript is a good thing: you can have ES6 features, now
ES6 compatibility is woefully lacking for most browsers found in the wild, which is definitely appealing if you want to use some of those cool features you hear about… especially the ones that most people gripe about the lack of in JS (classes and inheritance) when compared to most other OOP languages.
Classes and Modules are now available to you, and down compiled . You can use the super cool (and often confusing on your first encounter) “arrow” functions notation for your Anonymous Functions. Rest functions where you can finally make your functions as flexible as you want them.
When you let TypeScript transpile your code you can have all of those amazing ES6 features with your current user base’s browsers! Yes, even Safari!
Why TypeScript is a good thing: You get type hints, type checking at compile time
Type annotations allow you to specify the exact type of input and output you are passing around your functions. This not only leads to implicit assertions of your types, but also allows for great real-time syntax checking if you are using an editor that supports it.
Also, the next time you try and pass a boolean variable to a function expecting a string, your compiler will complain “LOUDLY” and refuse to compile your crap code. Using explicit variable types is the best documentation you can provide and its built into the code you are writing.
How to Install / Use It
Install TSC via NPM
npm install -g typescript
Then follow along in the easy to understand QuickStart / HelloWorld from the TS team: http://www.typescriptlang.org/docs/tutorial.html
If you cannot install it, you can also try the TS playground: http://www.typescriptlang.org/docs/tutorial.html
Who is really using TypeScript?
Well, for one, Microsoft is using it on quite a few internal projects. The Angular 2 team actually wrote the majority of the new framework using TypeScript. Also, the popular project management tool Asana’s team made a rather well publicized switch to TypeScript recently.
Should I use TypeScript?
The simple answer is, sure. Why not. I would give it a shot and try and work it into your workflow and see how it goes. Thankfully it plays nice with vanilla JS as well.
Leave us a note in the comments if you actually use TypeScript, or have a good reason not to use TypeScript, in your work.
In our previous posts, we discussed how to use some tools to explore and debug legacy code. This blog post will explore one of these tools that I personally use quite often in depth: Xdebug and Remote Debugging.
We’ll explore the installation, the required settings tweaks, and some basic tools and workflows to get you started. The least fun and hardest part of this whole process is the installation.
Having xdebug up and running will speed up your code investigations and will really help you dig into troublesome code. It will also give you the best insight into code you aren’t familiar with works without resorting to die statements and var_dumps for small windows.
Please only install this on your development and staging environments! Do not install this on any public facing server!
I want to take a minute and explain the concept of remote debugging with Xdebug. Until a few years ago, I would install XDebug only to get the “pretty error printing” features. While these features allowed some better control over how I was viewing errors and my var_dump results, it really added nothing I critically needed. Remote debugging now makes XDebug a short list of ‘need to install’ things when setting up a new environment.
Xdebug offers mechanisms to allow you to set breakpoints in your code to stop it’s execution and view the current state. This means you can say “stop here and let me take a look around at what the code is doing at this moment” on the server itself. You actually connect to the server and can poke around, set some conditional break points (where you stop execution when a variable is set to a certain value) and even evaluate some raw PHP on the server given certain conditions.
To accomplish this, you must connect a debugging tool to your server with a specified and exposed port and talk to it using a protocol provided by XDebug. Your debugger is the tool you use on your machine, XDebug is the tool/port/settings collection you use to connect to your server.
If this sounds like the basic IDE debugging tools you have used with other languages like C++ and JAVA (and also like something overcomplicated for being such a normal feature for other development stacks), it should. It’s pretty much the same thing. The biggest difference here is that this was not a widely used debugging method for hosted PHP. I’d like to help change that with this blog post.
Installing the Xdebug Extension
The xdebug project and github page offer some installation instructions that feel woefully lacking. Also, they offer little advice tailored to individual setups and environments. I’ll try and provide some examples of common installation methods.
Please note that these methods assume you are installing on the same server you host your development environment that serves the PHP code you wish to debug. This means, if you are running a vagrant box or docker container to host your code, install xdebug on this server instance. If you host your locally code on the same machine you are edit and maintain the code on, install xdebug on this machine. See the section above for some clarification on remote debugging.
All of these instruction assume you have administrator access and some level of comfortability with the *unix command line. If you do have access to your server in this capacity, or you are not comfortable with running these commands, you might want to find a grown up to help you.
pecl / pear
You can install Xdebug extension with the pecl tool and then tweak your php.ini file to include the installed extension. The official docs recommend this route first actually. The installation instructions are the same with the pear tool as they are for pecl. I have found this is the easiest installation method if you are running your server on a MacOS environment.
After you are sure you have pecl installed, run this command on your command line.
pecl install xdebug
apt-get / yum
If you are running your server on an Ubuntu/Debian/CentOS machine, you can install the xdebug with your specific package manager.
sudo apt-get install php5-xdebug
yum install php5-xdebug
This is a method I have never tried personally but I know there are some recipes specifically for installing xdebug with homebrew.
From what I read, you will need to add the homebrew-php repository and install this from the command line as well. Check out this repo link for more information.
Compiling it yourself
Another method I have never tried personally, but I know its possible. If you are want to do this yourself, you might be beyond the scope of this post. I’ll just point you to the project page for the most up to date information.
Update your php.ini file
Find your newly installed php extension and add this line to your php.ini file
Replace the “xdebug.so” file with whatever your tool installed. It’s also safe to create a symlink with the filename “xdebug.so” as well. If you have trouble finding this file, try the following command to find the extension file:
find / -name ’*xdebug*.so’ 2> /dev/null
Verifying your XDebug Installation
Restart apache and create a test file called test.php with the following lines of code and load it into your browser:
Search for “xdebug” and you should see something like this in your browser:
If you see a line that looks like the one highlighted above, congrats, you have installed xdebug!
You will need to expose some ports on your server to allow connections from your debugging client. How you accomplish this will certainly depend on your individual environment setup, but I would like to note this to save you the time I lost trying to find out why I could not connect.
And we will explain the port you will need to be expose and forward in this next section…
Xdebug INI Settings
Here are some of the INI settings you will need to update in order to enable remote connections. These settings will be found in your php.ini file, or a possible xdebug.ini file if one was created by your install method.
This setting allows you to specify an address where you debugging client is connecting from.
In most cases, this will be set to “localhost”, but may differ in your development environment.
This setting is ignored if xdebug.remote_connect_back is set to TRUE. See more info below.
This setting enables remote debugging, turn this on!
This setting allows you to specify a port for your debug client to connect to the remote server with. You will need this value when configuring your remote debugging tool.
This is typically set to 9000 but you can update this to any port that isn’t being used if you feel contrary.
This setting allows you to specify the amount of array children and object’s properties are shown when you use a var_dump or use your debugging client’s function trace tool.
By default this is set to 128, but you can set it to -1 if you want to remove the limit entirely.
Like var_display_max_children, this setting allows you to set a maximum string length that is shown when variables are displayed in var_dumps or function traces.
By default this is set to 128, but you can set it to -1 if you want to remove the limit entirely.
Another setting that allows you to set a limit when using var_dump or function tracing, but this one sets the nested levels of array elements and object properties displayed.
By default, this is set to 128, but again if you live dangerously you can remove the limit entirely and set it to -1.
Setting this value to true will disable the @ (the “shut up”) operator entirely.
This is super useful when you find out when you predecessor was just hiding a critical error behind the @ operator and you can finally go to be because you found the elusive notice showing the variable was never set in the first place and you had no idea and thats why you can’t get the page to load when you don’t have a cookie set in IE 9.
Setting this value to true will allow you to connect and attach a remote debugging client to your server from any address.
This setting is great for shared development environments but is quite dangerous since it will just allow anyone to connect who tries. YES, anyone.
Also of note, this will override the xdebug.remote_host setting.
While I personally like to use the stand alone tools, I do know a lot of people who prefer to use these editors to remote debug.
While I’m sure a cursory google search can lead you to some better instructions on how to install and configure these tools, I thought it was worth mentioning since a lot of people use these tools and they offer the remote debugging tools you might want to use.
This is a tool I use on an almost daily basis. Its relatively small and lightweight, and gets out of the way when I am done. I also mentioned it in our last blog post. I do need to note that this tool does not seem to be updated frequently and occasionally crashes without warning. That being said, I still highly recommend it.
All of us will encounter legacy code, and most of us will ‘inherit’ code to maintain. In our first post on legacy code, we talked about getting the things you need to start working on a project. In this post, we will talk about how you can evaluate the backend code you will most likely have to start digging in to start new features or squashing bugs.
While you will encounter a significant amount of UX or front-end issues when starting on a new project, you are also just as likely to have to track an issue to the underlying backend code. The backend not only creates the foundation for your web app but its also the last line of defense for your back end code. At minimum issues on the backend will cause confusing results or headaches. At worst, issues on the backend will expose some of the most vital parts of your webapp to exploits.
Most backend code is the result of a lot of hours and hard work; it can be extremely confusing to wrap your head around the basic concepts let alone the deeper portions of the code. We’ll discuss some basic patterns and explain some of the tools we use to explore code, PHP code in particular, when we take on a project with some ‘baggage’.
I like to split the application into small semantic sections. You can either break an application down into ‘workflows’, the actions a user may perform with an application; or as ‘roles’, things a particular actor will use a web app for. While this may sound like a very high level activity for inspecting back end code I think its crucial for understanding the application itself.
Once you have split the code into sections, trace the entire workflow. Follow the code from the beggining of an action to the resulting output. Tracing through the code will allow you to completely understand it.
Debugging and Tracing Tools
This is one of my favorite tools and is the first thing I install when I set up a new environment. Not only does this give me much easier to read error outputs, but it also gives you some great tools for interactive debugging. Seriously, if you do nothing else I suggest, at least install xdebug.
Interactive debugging is the best tool for finding that super stubborn bug or finding out why something isnt working as you expect. With a remote interactive debugger you can set break points and view exactly what the code is doing at a given point in time. You can actually inspect a variable value and watch it change as you step through the lines of code. This is something you should get excited about. Check out the screenshot below to see this in action with an example Erdiko project:
I use MacGDBp, a Cocoa based debugging tool that allows you to set break points and view the code when you set break points. I’ve been told that PHPStorm and even Sublime have some interactive debugging tools, I have not used those. MacGDBp is a bit dated, and I think almost abandonware, but it is still an indispensible tool in my aresenal. Check out the MacGDBp project docs for more info about the feature set and how to install it.
Personally, I would recommend using MacGDBp along with xdebug and the chrome extension ’chrome-xdebug-enabler’ to interact with your debugger. Using this extension you can conditionally turn the debugging off and on as you wish when refreshing the page.
I should note that while I personally use MacGDBp with vim, many other editors also include some remote debugging tools. PHPStorm has this functionality built in, but there are plugins for SublimeText and other full editors. We will explore those in a later post.
PHPLint and PHPCodesniffer
There are two great tools for getting some high level information about a PHP codebase: PHPLint and PHPCodesniffer.
PHPCodesniffer evaluates code based on a provided set of rules and standards and outputs a report that can give you a good idea of how ‘bad’ things look under the hood. It’s actually two tools: phpcs and phpcbf. phpcs evaluates the code, phpcbf attempts to fix the code. Personally, I like to use some discretion when tweaking code, so I would reccomend using phpcbf sparingly.
PHPLint is another tool, very similar to PHPCS that also outputs information on a code base based on rules and validation sets. This one is also very useful for generating user docs based on docblocks. This can be EXTREMELY useful when you need to collect a lot of information about a large codebase and create some baseline documentation for your team.
Unit testing is often touted as the best prevention of introducing new bugs and finding conflicting code. I would also like to note, most people ignore the fact that introducing unit testing to legacy code is a painful process. Code written without testing in mind can often be a pain to manage dependencies and ‘magically’ required code.
This is a topic that actually deserves its own blog post, but I do want to mention it in this one.
… to be continued
In my next post, ill include some instructions on how to install xdebug on your local *nix development environment.
All of us will encounter legacy code, and most of us will ‘inherit’ code to maintain. Even on the freshest of projects 99 % of the time you will encounter some ‘baggage’ code that we will have to maintain. This is especially true as a contractor for any PHP project. Deservedly or not, PHP has a bad reputation for code quality
The good news is that you can mitigate some of the worst aspects of a legacy project by doing some work up front. Making sure you have all the assets you need up front can prevent embarrassing emails to the client asking for random things and generally making your life easier.
For this first of three blog posts about legacy code, we’ll spit this into two lists: Things you need and nice to haves.
Things you need:
This should be a no brainer. You need access to the server to make sure you have the most up to date code, and hopefully you will be deploying some updates in the near future. Yes, this may seem very obvious but you would be surprised how easy it is to forget this step in the excitement of a new project.
Ask the client how they access and how the previous team accessed the server. Make sure you try and actually login with these credentials as well. After you successfully get access, you may need to deactivate or in the minimum change some passwords of the previous server users.
Code in Version Control
You will also want access to the most up to date version of the codebase, hopefully in a form of version control. Again, while this seems like a no-brainer, it is very important to track changes you make once you start to dig into the code. It can also provide some information as to what the previous developer was thinking with the code in the past.
Once you have access to this you can convert it to your VCS of choice or continue to use the one provided. You will really want to consider keeping the VCS the same if you are working with other existing teams or with the client who needs access to the code.
It is also worth your time to ensure that the code in the VCS is sync’d and up to date with what is on the production server. There are many file comparison tools that can be used to compare entire directories which we will cover in our next post. While you can assume a previous team who had a code base in version control has kept things up to date… like the Russians say: Trust, but verify.
Ask for any documentation the client can provide, good or bad. Something is better than nothing.
You should also plan on converting this into some form of living document you can edit and share easily. A self hosted wiki works great for tracking changes, but so does a markdown file stored in the repo itself. Anything easy to edit will remove another barrier that will prevent you from updating documentation, and already loathsome task.
You should be documenting everything as you explore the project. Document the file and database structure, document the existing workflows. Ask the client how things “should work” and then note how things are broken. Get it all into a living document so you can track your progress.
Nice to Haves:
A Shared Project Management System
Create a method in which you can communicate your project status with the customer. This will also provide a great resource in which you and the client can document bugs and future updates.
A shared system will allow you to manage your project beyond instant messages and emails. It also provides instant feedback to the client allowing them to see ‘exactly what they are paying you for’ and allows for the easier exchange of ideas.
If you’re lucky, the client may already have one (and be trained on how to use it.) It’s also very likely the client does not know how or what a Project Management System is, in which case priority number one is showing them how it is useful.
A separate Staging and local development environment
Tools like Docker and Vagrant allow you to spin up servers quickly and provide tools to re-recreate the server after you mess it up. This will become very important as you dig in and mess things up while trying to determine exactly what is wrong.
Our next post will focus on some frameworks and tools we commonly use to evaluate legacy code. We’ll also provide some basic examples of how to use these tools.
The AJAX paradigm really launched the web into primetime some 10+ years ago, but now its almost expected. Now it’s a ubiquitous part of the web landscape. Most web apps now resemble an ‘app’ in regards to their UX and users ‘expect’ content to dynamically update without a page refresh. In the past, we have used some great tools like jQuery to cobble together a basic app to interact with our page and an AJAX backend, but a framework like AngularJS adds some sanity and structure to what could have been a mess of spaghetti code.
The most common use cases for AJAX are dynamic content and form interactions. For example, if you have a large list of tabular data, you can load it via AJAX to show your basic page to a user without having to render the table on the server. Forms can be validated with JS and sent to the server in the ‘background’ so the user doesn’t have to leave the page. There are MANY other use cases for AJAX, but I think this covers the majority you will encounter when developing a web app.
HTTP / XHR
Most browsers you will encounter, or your clients will use, will have access to the HTTP API known as XHR (it’s safe to assume that anything above IE 5.6 will allow you access to this API). While some browsers offer Fetch support, I will skip that for the purposes of this blog post.
In general, you will provide AJAX access via a service. Services are a part of the Dependency Injection patten that makes AngularJS so modular. Creating a piece of code that allows you to encapsulate all actions that make AJAX calls allows for better re-use and easier testing.
Observables vs Promises
Too often used tools/patters for working with asynchronous data structures are Observables and Promises. While you may be familiar with Promises as a pattern, and most likely have used something like promises in the past, Observables are a pretty new concept to me.
In short, Observables are “a push based collection” using the observer pattern. Put simply, this is a queue of objects with some amazing manipulation methods and hooks to allow you to detect when something occurs within the queue. It’s pretty great for dealing with a dataset that needs to be lazy loaded or can possibly get updated in the life cycle of the application.
Here is a simple example based on the angular.io Hall of Heros example showing an observable request:
A promise is “a way to define actions or computations once an async event completes”; an observable is “way to define computations or actions that happen when one or more events in a stream occur”.
Here is a simple example based on the angular.io Hall of Heros example showing an promise based request:
The key take away from comparing these two tools: observables and promises are both great tools for async programming like AJAX, but observables are more like a stream of data than a ‘one time request of data’. We’ll touch more on this in future blog posts.
Here are some code examples that borrow very heavily from the HTTP Client example found on the Angular.io site.
While Components have been around in some shape or form around the web, Angular 2 is based around these amazingly flexible elements.
Components in AngularJS 2 will entirely replace controllers. In fact, they will also replace the concept of a module. They look like a directive, but actually act like a controller.
A component is essentially an HTML element that uses Shadow DOM to encapsulate its own scope and behavior. What this really means: your component has its own variable scope. What happens in your component, stays in your component. You can however inject your components into other components or decorate them to add functionality.
Here is an example of the previous burrito example above implemented in AngularJS 2 showing a component in action:
Decorators via Annotations
Decorators are a simple design pattern that we can now use to update the values and context of a component without introducing new behavior.
Seriously, this is great. You can just apply a decorator to your directive and change its variable values without actually tearing into its guts. Change your components color from ‘Red’ to ‘Blue’ at runtime externally without hacking away at its internal functionality or exposing some getter after the fact.
Currently, this is available in the upis provided by TypeScript, but is
A Focus on Dependency Injection
AngularJS 1.x certainly used the concept of dependency injection and promoted it with the usage of services and factories. I don’t think I need to spend a lot of time stumping why and how this can make for better encapsulation and easier re-use of code.
AngularJS 2 will take this a step further and encourage you to use dependency injection with components. Write a login component and inject it into
Previously, we needed to let the Digest / Apply loop cycle through your variables, or use the oft-maligned scope.$apply to let your app know that something changed. ZoneJS will now be handling all of this.
Zones is able to encapsulate the entire scope of your component and is aware of when asynchronous events start and stop.
While getting away from $apply and not having to worry about your scope is great, here comes the best part: ZonesJS will speed up execution time as much as 5x compared to AngularJS 1.x code.
The bad news: Zones is only available for modern evergreen browsers. This means if you are using IE10 or below you will not get the to use this amazing toolset. Angular 2 will have fallbacks with dirty value checking and poly-fills to make sure this is all invisible for you, but you will not see the major speed increase you would get from actually using ZonesJS.
TypeScript is a superset of ES6 and gives us some amazing features.
AngularJS 2 will be written in TypeScript, but this doesn’t mean you have to use it. I can say that I plan on using it as I think this will be an area
Ok, this sounds great. How do I prepare to upgrade?
I won’t go too much in depth on this but there will be upgrade paths and plans if you dont want to just ‘start over’ with your existing angular app.
As I’m sure you know if you are reading this, the AngularJS team is planning for a major version release “very soon” that will include some major paradigm shifts. A lot of the things you learned while teaching yourself AngularJS 1.x will just not be present in AngularJS 2.
AngularJS 1.x is stable and will definitely be around for a long while with long term support from the original team. But do you really want to pass up on some of those amazing features (3-5x Performance increases, the ability to use Server Side Rendering, bragging rights)? No, of course not.
Just to make sure we can explain the concepts of Angular 2, let’s briefly review the main concepts of Angular 1.
Modules & Controllers
A module can be thought of as the container that holds all the different parts of your AngularJS application. These have the advantage of making your code declarative and well encapsulated.
Custom HTML elements used to enable and interact with AngularJS. This cool feature is how we instantiate your app (`ng-app`) or create custom elements that transform data and views with JS logic stored in your models and controllers.
Here is an example of a directive in AngularJS 1.3 that replaced a `<burrito />` directive with an image of a burrito:
The Application model and context, defined by an angular element. Defined hierarchically, scopes can be passed between elements
It’s important to note that Controllers, Services and Directives all have their own nested scopes. This can get messy when you are passing around data and need to make sure you aren’t polluting your own scope.
While this is a great feature, it’s incredibly slow. Every digest cycle has to check ALL of these variables and update them appropriately.
Data binding is that magic that lets you sync data between your models and your view. In a sentence: your model’s data is bound to the view and your view is bound to your model’s data.
This is that awesome thing that does that sweet ‘live’ updating of values in your forms. Most likely, this was the huge selling point when you first started learning about AngularJS and the ‘reactive’ web.
We’ll explore where these things start to differ in Angular 2 in our next post