Directives-Workshop

Angular allows us to create these great things called directives. Directives are essentially small pieces of functionality our app needs that can be bundled up into individual components.

These components allow us to reuse code within our project, and throughout other projects. Creating your own directives can be odd at first because we will be using a lot of built in Angular functionality to do this. For now consider these things as autoMagical and then once you've created a few go look into how Angular is interpreting the directive.

#The Anatomy of an Angular Directive - a reference.

	var app = angular.module('NAME-OF-APP', []);

	app.directive('nameOfDirective', function() {
		//our directive's name 'nameOfDirective' will be parsed to show up as 'name-of-directive' in our HTML.

		return {
			  //you have 4 restrict options. You can use any of the 4 in any combination.
			  //{'E': 'Element', 'A': 'Attribute', 'C': 'Class', 'M': 'Comment'}
			  //typically we create them as Elements or Attributes.
			restrict: 'EA',
			scope: {
				name: '=name' //The name of the directives scope and be set
			},				  //in the name attribute on the directive's element.
			template: '<div><h1>Hello World</h1></div>',
			  // the template can take raw HTML, or a file path that leads to an HTML file.
			  // Like so:
			templateUrl: 'app/views/directiveView.html',

			controller: function($scope) { //We can create a controller in our directive!
				$scope.test = 'OMG!';
			},
			  //this allows us to create a special controller that nothing else can touch.
			replace: true, //If we are using a template, we can choose to insert it's value wherever we call the directive.
			link: function(scope, elem, attr) {
		          // scope is the directive's scope,
		          // elem is a jquery lite (or jquery full) object for the directive root element.
		          // attr is a dictionary of attributes on the directive element.
		      	elem.bind('dblclick', function() {

		      });
		    }
		}

	})

####Steps to complete the "pending" directive

  • Hide, disable, or change the text of the submit button
  • Show a spinning icon or gif while we wait for our data
  • Hide the spinner when our data returns
  • Reset the submit button to its original condition
  • You may need to use $q and setup some promises
  • Inject $q into the directive not the link function
  • remember scope.request === to the function on the controller.
  • Don't let your controller function start until the "element" is "clicked"
  • Make sure your controller function is returning itself and its promise.
  • This will be difficult, don't give up. Tackle one problem at a time.

###Step 3

####Create Notify Directive

Now that you have a super cool directive that you can drop in anytime you need to make a call to a server. Lets make another directive that will be just as reusable as the last. Make sure you look up Html5 Notifications. They are built into most modern browsers and can therefore be very helpful for notifying us when an event occurs. Think of DevQueue; wouldn't it be nice if Mentors got a small notification whenever a student enters the Queue? With this directive we should be able to accomplish that task fairly easily.

Go ahead and setup a brand new directive and lets call it 'notify'. The setup here will be a lot like our pending directive, however the link function will be what changes. Follow the same process as before and then put this in as a freebie at the top of your link function. Although most modern browsers have built in notifications and they pretty much all function the same way they are not stored in the same location on the window so we are going to setup a simple "or" statement that will help make sure we are using the correct notification for each browser. Because it would be annoying for any site to give you popup notifications without your consent, users have to grant permission to receive notifications. This permission is saved as a cookie so it will remember the setting each time you go to the site. Because it uses Cookies make sure you use something like http-server when testing.

	var Notification = window.Notification || window.mozNotification || window.webkitNotification;
	Notification.requestPermission(function (permission) {
				//console.log(permission);
			});

Moving right along...if you look at console.log(Notification) you would see that in each of these browsers Notification is a constructor. Remember in Js constructors use an initial capital letter. This means that for each notification we will be creating a 'new Notification()' instance. This constructor is setup to take in two parameters a string for its title and then an object with the rest of its properties. (title, {body: '', icon: ''}). Practice getting these notifications to work first with some hard coded values, then think about what you have learned to pass in variables that are on $scope from your controller.

####Steps to complete the "Notify" directive

  • Utilize scope {title: '=', body: '=', icon: '='}
  • Remember to setup your HTML with the correct naming conventions
  • Create a function that can be called on elem.click()
  • Use a callback in elem.click() to pass your params to the Notification Constructor
  • Again this will be difficult don't give up. Tackle one problem at a time. Use your resources.

###Step 4

Because you wrote some super cool directives go back to some of your previous projects and add in your myDirectives.js and don't forget to inject your module as a dependency angular.module('Itunes', ['ngGrid', 'myDirectives']) Then just drop into the Html, add in the required attributes, and watch your directives work seamlessly.