Article 5BRTD CodeSOD: All the Angles

CodeSOD: All the Angles

by
Remy Porter
from The Daily WTF on (#5BRTD)

Web frameworks are a double edged sword. They are, as a rule, bloated, complicated, opinionated and powerful. You can get a lot done, so long as you stick to the framework's "happy path", and while you can wander off and probably make it work, there be dragons. You also run into a lot of developers who, instead of learning the underlying principles, just learn the framework. This means they might not understand broader web development, but can do a lot with Angular.

And then you might have developers who don't understand broader web development or the framework they're using.

Dora has someone on their team which meets that criteria.

The first sign there was a problem was this line in a view object:

<a href class="btn" ng-click="doSomething()" ng-disabled="$ctrl.numFormErrors > 0">save form</a>

First off, ng-disabled adds the disabled attribute to the DOM element, which doesn't do anything to anchor tags. The goal here is to disable the "save" button if there are validation errors, and already the goal has been missed. However, that's not the weirdest part of this. Angular provides loads of helper variables and functions, including a form.$invalid which helpfully tells you if there are validation errors. So where is $ctrl.numFormErrors coming from?

$scope.$watch("form.$error", function(errors) { $ctrl.numFormErrors = 0; $ctrl.fieldsWithErrors = []; _.forEach(errors, function (errs) { for (var i = 0; i < errs.length; i++) { if ($ctrl.fieldsWithErrors.indexOf(errs[i].$name) < 0) { $ctrl.fieldsWithErrors.push(errs[i].$name); $ctrl.numFormErrors++; } } });}, true);

Oh, that's simple enough. So much clearer than using the built in form.$invalid.

If you're not "up" on Angular, and without diving too deep on the mechanics, $scope.$watch registers a callback: every time form.$error changes, we invoke this function. In this callback, we clear out our $ctrl.numFormErrors and $ctrl.fieldsWithErrors. The keys of errors are validation failures, like maxlength and pattern, so we use the lodash library to forEach through each of those keys.

The values are arrays of which fields have the given error, so we for loop across errs (I guess we didn't want to use lodash again?). If we haven't already tracked an error for the field with this $name, we add it to our array and increment the numFormErrors field.

Now, every time the user edits the form, we'll have a list of exactly which fields are invalid, and an exact count about how many there are. That's not something Angular makes obvious, so we've accomplished something, right?

Well, the only problem is that this code never actually uses $ctrl.fieldsWithErrors and it only ever checks if $ctrl.numFormErrors > 0, so no- we didn't need to do any of this.

Dora threw out the $watch and just replaced the anchor with a button done the "Angular" way:

<button class="btn" ng-click="doSomething()" ng-disabled="form.$invalid">save form</button>
proget-icon.png [Advertisement] ProGet's got you covered with security and access controls on your NuGet feeds. Learn more. TheDailyWtf?d=yIl2AUoC8zAmfOYeFz7Xe8
External Content
Source RSS or Atom Feed
Feed Location http://syndication.thedailywtf.com/TheDailyWtf
Feed Title The Daily WTF
Feed Link http://thedailywtf.com/
Reply 0 comments