I am building a new SPA front end to replace an existing enterprise's legacy hodgepodge of systems that are outdated and in need of updating. I am new to angular, and wanted to see if the community could give me some perspective. I'll state my problem, and then ask my question.
I have to generate several series of check boxes based on data from a .js include, with data like this:
$scope.fieldMappings.investmentObjectiveMap = [
{'id':"CAPITAL PRESERVATION", 'name':"Capital Preservation"},
{'id':"STABLE", 'name':"Moderate"},
{'id':"BALANCED", 'name':"Moderate Growth"},
// etc
{'id':"NONE", 'name':"None"}
];
The checkboxes are created using an ng-repeat, like this:
<div ng-repeat="investmentObjective in fieldMappings.investmentObjectiveMap">
...
</div>
However, I needed the values represented by the checkboxes to map to a different model (not just 2-way-bound to the fieldmappings object).
To accomplish this, I created a directive, which accepts a destination array destarray which is eventually mapped to the model. I also know I need to handle some very specific gui controls, such as unchecking "None" if anything else gets checked, or checking "None" if everything else gets unchecked.
Also, "None" won't be an option in every group of checkboxes, so the directive needs to be generic enough to accept a validation function that can fiddle with the checked state of the checkbox group's inputs based on what's already clicked, but smart enough not to break if there is no option called "NONE".
I started to do that by adding an ng-click which invoked a function in the controller, but in looking around Stack Overflow, I read people saying that its bad to put DOM manipulation code inside your controller - it should go in directives. So do I need another directive?
So far: (html):
<input my-checkbox-group
type="checkbox"
fieldobj="investmentObjective"
ng-click="validationfunc()"
validationfunc="clearOnNone()"
destarray="investor.investmentObjective" />
Directive code:
.directive("myCheckboxGroup", function () {
return {
restrict: "A",
scope: {
destarray: "=", // the source of all the checkbox values
fieldobj: "=", // the array the values came from
validationfunc: "&" // the function to be called for validation (optional)
},
link: function (scope, elem, attrs) {
if (scope.destarray.indexOf(scope.fieldobj.id) !== -1) {
elem[0].checked = true;
}
elem.bind('click', function () {
var index = scope.destarray.indexOf(scope.fieldobj.id);
if (elem[0].checked) {
if (index === -1) {
scope.destarray.push(scope.fieldobj.id);
}
}
else {
if (index !== -1) {
scope.destarray.splice(index, 1);
}
}
});
}
};
})
.js controller snippet:
.controller( 'SuitabilityCtrl', ['$scope', function ( $scope ) {
$scope.clearOnNone = function() {
// naughty jQuery DOM manipulation code that
// looks at checkboxes and checks/unchecks as needed
};
The above code is done and works fine, except the naughty jquery code in clearOnNone(), which is why I wrote this question.
And here is my question: after ALL this, I think to myself - I could be done already if I just manually handled all this GUI logic and validation junk with jQuery written in my controller. At what point does it become foolish to write these complicated directives that future developers will have to puzzle over more than if I had just written jQuery code that 99% of us would understand with a glance? How do other developers draw the line?
I see this all over Stack Overflow. For example, this question seems like it could be answered with a dozen lines of straightforward jQuery, yet he has opted to do it the angular way, with a directive and a partial... it seems like a lot of work for a simple problem.
Specifically, I suppose I would like to know: how SHOULD I be writing the code that checks whether "None" has been selected (if it exists as an option in this group of checkboxes), and then check/uncheck the other boxes accordingly? A more complex directive? I can't believe I'm the only developer that is having to implement code that is more complex than needed just to satisfy an opinionated framework.