In this delivery, we are going to refactor our birth date validation and html into a semantic reusable component.
If you would like to revisit out of the box validations, creating a custom validation over a single input, read Part 1 and
if you would like to revisit creating validations over complex objects go over Part 2.
Step 4 - Refactoring
The birth date validation is a three part deal.
In order to preserve some sense between these and because there is a real possibility on reusing these three select options together,
we are going to take a first stub at transforming this into a component.
We are going to write a new directive called “myBirthDate” that will take care of generating this component for us.
It will know nothing about validation. When we are done, both our new component and validation directives will work together.
As always Test Driven Development…Unit tests first.
We need to write unit tests to make sure our directive will generate the three select elements (day, month and year) with the options we set from the constants.
In order to make options matching easier, we will create a custom jasmine matcher that will iterate over all options and
use some underscore magic to compare the gathered options against a list of options we will pass to the function.
If there is no difference, we return true so the expectation is fulfilled.
Now lets write some tests.
And now we write the directive…It is going to be a very simple directive. It is reason to be and to change is load an html block with a preloaded data set as options.
As you can see, Im injecting the data set I was previously using on our validation directive and initializing those values in the scope using the link function.
In order to avoid adding more moving pieces to this post, I kept the html code inside the template attribute.
You should know you can use templateUrl and $templateCache so as to request the html using an http call or from cache.
If you are familiar with ngInclude, templateUrl works just like it.
**Best Practice:** Unless your template is very small, it's typically better to break it apart into its own HTML file and load it with the templateUrl option.
Updating our validation directive
Having done this, we need to make a few adjustments on our “myValidateBirthDate” directive constructed on Part 2.
- We remove any notion about the data set and the select options prepopulation.
- We need to start watching at the model called "date". This is the one that it is going to change now.
Having our unit tests provides all the support we need to make sure nothing is broken.
I’ve gathered all our birth date directives’ unit tests into one file.
If you would like to play/see with the unit test, launch this demo.
And this is how out html looks like now:
And here is the whole picture so far:
If you would like to play/see with the complete example, launch this demo.
What does this have to do with Validations?
The progression that it is been laid out in these 6 steps (4 so far published) aims to demonstrate validations as well as a refactoring methodology taking simple or complex validations into components.
Step 5 will cover a very small tweak so we can reuse both directives and have multiple instances on the same page.
Picture a Flight booking form where you need to enter multiple passengers birth dates.
Step 6 will cover the refactoring of the error handling on the html so we can support multiple instances of passengers
taking advantage of the same semantics we’ve already built.