This is a question about whether my coding style follows AngularJS best practices.
One of the selling points to Angular is directives. Directives allow you to create custom DOM with elements or attributes you create. I've found myself creating lots of directives, thinking of each one as little controls to be placed on the page. Looking back, I'm wondering if I'm too directive focused and if Angular directives should only be used when you need a custom link method?
What I find myself doing a lot is wrapping up some HTML in a directive with a simple controller that does one or two basic things. I have a lot of code that looks like this code of mine from a blog post:
'use strict';
angular.module('solrAngularDemoApp')
.directive('searchResults', function () {
return {
scope: {
solrUrl: '=',
displayField: '=',
query: '&',
results: '&'
},
restrict: 'E',
controller: function($scope, $http) {
console.log('Searching for ' + $scope.query + ' at ' + $scope.solrUrl);
$scope.$watch('query', function() {
$http(
{method: 'JSONP',
url: $scope.solrUrl,
params:{'json.wrf': 'JSON_CALLBACK',
'q': $scope.query,
'fl': $scope.displayField}
})
.success(function(data) {
var docs = data.response.docs;
console.log('search success!');
$scope.results.docs = docs;
}).error(function() {
console.log('Search failed!');
});
});
},
template: '<input ng-model="query" name="Search"></input>' +
'<h2>Search Results for {{query}}</h2>' +
'<span ng-repeat="doc in results.docs">' +
' <p>{{doc[displayField]}}</p>' +
'</span>'
};
});
So now I can think of my search results as a little widget to embed on the page:
<search-results solrUrl="..." etc></search-results>
OK Let's say I take the next step in my application and want to display more information about the individual documents from the search results. My inclination up to this point has been to create a custom directive, like a little "widget" that handles all the functionality here. If I need to say wrap-up how a document from the search results gets displayed, I'll add a directive like lets say "docDisplay". Something like:
angular.module('solrAngularDemoApp')
.directive('docDisplay', function() {
// same pattern as above
});
Then in the template for search Results, I'll change out my template:
template: '<input ng-model="query" name="Search"></input>' +
'<h2>Search Results for {{query}}</h2>' +
'<span ng-repeat="doc in results.docs">' +
' <doc-display></doc-display>' + // THIS LINE CHANGED
'</span>'
I may or may not use prototypical inheritance of $scope or use an isolate $scope, depending on how strongly I feel this directive is tied to the parent.
After writing a lot of code this way and learning more about Angular, I realized that I could just have
- Thrown all this HTML into my main HTML
- Used ng-controller on specific pieces of HTML
As nothing here takes advantage of the link functionality of the directive (binding DOM events to create some custome functionality) and my directives are just a bunch of HTML and controller code I'm left wondering the following two questions:
- Is it ok to use directives like this to break up my UI? or am I thinking too much in the directives==controls mindset
- Should I avoid directives when there's no link function? and just stick with plain-jane HTML with ng-controller?
ng-controller
(its not reusable), use custom directives and TDD those directives. You should use HTML as your vehicle of user state instead of relying on implicit scope hierarchy to help communicate your intent better, and its actually very rare to have a section of your code that doesn't need input that wouldn't be better as a filter. \$\endgroup\$