design, formal elements, or elements of art, are the vocabulary with which the visual artist composes. These elements in the overall design usually relate to each other and to the whole art work.” What is composition?
elements, comments, or CSS classes • Componentize functionality with HTML • Create custom HTML elements <my-hello-world en="es"></my-hello-world> <name-tag name="Jeremy"></name-tag>
}, template: 'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; Restrict to element declaration (i.e. `<name-tag></name-tag>`) E - element A - attribute C - class name
}, template: 'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; Templates template - literal template templateUrl - url or script id for template
}, template: 'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; link manipulate DOM or set some defaults on scope controller add to scope too, preferably for exposing an API Set up
}, template: 'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; <p> <name-tag name="Jeremy Fairbank"></name-tag> <!-- Hello, my name is Jeremy Fairbank --> </p> <p> <name-tag></name-tag> <!-- Hello, my name is Joe Schmoe --> </p>
}, template: 'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; <p> <name-tag name="Jeremy Fairbank"></name-tag> <!-- Hello, my name is Jeremy Fairbank --> </p> <p> <name-tag></name-tag> <!-- Hello, my name is Joe Schmoe --> </p> Supplying the attribute value
'Hello, my name is {{name}}', link: function(scope) { if (!scope.name) { scope.name = 'Joe Schmoe'; } } }; <p> <name-tag name="Jeremy Fairbank"></name-tag> <!-- Hello, my name is Jeremy Fairbank --> </p> <p> <name-tag></name-tag> <!-- Hello, my name is Joe Schmoe --> </p> Directives Review Using the default value
a large problem • Apply design principles to directives • Build app in terms of directives • Decompose large directives into small reusable directives • Refactoring and adding new features becomes more manageable
the flow of data • Handling model data among directives • Many approaches with pros and cons App Directive Directive Directive Directive Directive Directive Directive Directive Directive
• Keep own copy of data instead of sharing • Higher coupling — child directives depend upon parent directive • Still need a parent controller to scope own images (cat versus nature)
– No parent scope to inherit from – Can’t access other scopes “easily” • Use object literal for scope definition scope: { age: '@age', name: '=', selectHobby: '&onSelectHobby' }
age: '@age', selectHobby: '&onSelectHobby' } Execute code in a “parent” scope (i.e. a callback) Function call with any parameter names. Uses function printHobby on parent scope (not the directive scope).
my name is {{name}}. I am {{age}} years old.</p> <p><input type="text" ng-model="name"></p> <ul> <li ng-repeat="hobby in hobbies"> <a href="javascript:void(0)" ng-click="selectHobby({ hobby: hobby })"> {{hobby}} </a> </li> </ul> </script>
and reusable • Think in terms of small pieces • Establish well-defined interface/API through HTML attributes • Juggle multiple points of state • More markup
methods of $scope. • Use events like a message bus to transfer data • Events travel vertically through scopes – Use parent scope event delegation for sibling directive communication
var items = []; $scope.$on('add:item', function(e, n) { items.push(n); }); // In a parent directive $scope.$on('select:greeting', function(e, greeting) { console.log(greeting.toUpperCase()); }); Events $on listens for $emit and $broadcast events and triggers the provided callbacks.
function(e, n) { items.push(n); }); // In a parent directive $scope.$on('select:greeting', function(e, greeting) { console.log(greeting.toUpperCase()); }); $scope.$emit('select:greeting', 'hello world'); $scope.$broadcast('add:item', 42); Events The first parameter is an event object like DOM events.
directive var items = []; $scope.$on('add:item', function(e, n) { items.push(n); }); // In a parent directive $scope.$on('select:greeting', function(e, greeting) { console.log(greeting.toUpperCase()); }); Stick to a naming convention like verb:noun.
have to touch entire app, just an individual directive – Touching multiple pieces may mean better SOC needed – SOC is evolutionary for the lifetime of the app