title: How to organize and reduce AngularJS controller size?
body: <p>I am building my first AngularJS app and am struggling to figure out how to organize my code into services/factories and directives.  My controller code keeps getting longer and longer and I know I must be doing something wrong.</p>
  
  <p>Originally my app had three controllers: "BuildingTypeController", "AddressController", and "LayoutController".  I used the ng-controller directive to attach each controller to each of my fieldsets.  However I encountered problems when:</p>
  
  <ol>
  <li>I needed to pass one controller's data to another controller to be able to use in the $scope.$watch code.</li>
  <li>When I needed to pass one controller's data to another controller in my Get... $http.get methods (replaced with hardcoded values in my code below).</li>
  </ol>
  
  <p>So then I went back and took all of my properties and functions and through them in one big "FormController".  This gives me the functionality I'm looking for, however I know this can't possibly be the right way to organize all of this code.</p>
  
  <p>If anyone could offer any advice on how to structure a long controller into smaller pieces I would greatly appreciate it.  Thank you!</p>
  
  <p>EDIT: The hardcoded datasets in this code were created to allow for the fiddle to work - they will be replaced with database calls and should not be factored into the "length" of the single controller.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var app = angular.module('formBuilder', []);
  
  app.controller('FormController', ['$http', '$scope', function ($http, $scope) {
      
      //This could really be thought of as "BuildingTypeController"
      var form = this;
  
      form.state = "";
      form.states = [];
  
      form.buildingType = "";
      form.buildingTypes = [];
  
      form.GetStates = function (buildingType) {
          //This will be replaced with $http.get later
          if (buildingType == null)
          {
            form.states = ["AZ","CT","NY"];   
          }
          if (buildingType == "Single Story") {
              form.states = ["AZ","CT"];
          }
          if (buildingType == "Mansion") {
              form.states = ["CT"];
          }
          if (buildingType == "Apartment") {
              form.states = ["CT","NY"];
          }
          if (buildingType == "Sky Scraper") {
              form.states = ["NY"];
          }
          
      };
  
      form.GetBuildingTypes = function (state) {
          //This will be replaced with $http.get later
          if (state == null)
          {
            form.buildingTypes = ["Single Story","Mansion","Apartment","Sky Scraper"];   
          }
          if (state == "AZ") {
              form.buildingTypes = ["Single Story"];
          }
          if (state == "CT") {
              form.buildingTypes = ["Single Story", "Mansion","Apartment"];
          }
          if (state == "NY") {
              form.buildingTypes = ["Sky Scraper", "Apartment"];
          }
      };
  
      //initializations
      form.GetStates();
      form.GetBuildingTypes();
  
      //This could really be thought of as "AddressController"
      form.addressId = "";
      form.addresses = [];
  
      form.GetAddresses = function (form) {
          //This will be replaced with $http.get later
          if (form.state == "AZ" &amp;&amp; form.buildingType == "Single Story") {
              form.addresses = [{
                  addressId: 1,
                  description: "123 Grove Ave"
              },{
                  addressId: 2,
                  description: "2352 High Court"
              }];
          }
          if (form.state == "CT" &amp;&amp; form.buildingType == "Single Story") {
              form.addresses = [{
                  addressId: 3,
                  description: "1515 Lark Ave"
              },{
                  addressId: 4,
                  description: "2 Front St"
              }];
          }
          if (form.state == "CT" &amp;&amp; form.buildingType == "Mansion") {
              form.addresses = [{
                  addressId: 5,
                  description: "6 Waterfront Dr"
              }]
          }
          if (form.state == "CT" &amp;&amp; form.buildingType == "Apartment") {
              form.addresses = [{
                  addressId: 6,
                  description: "13 Center St"
              },{
                  addressId: 7,
                  description: "5985 Elizabeth Court "
              }]
          }
          if (form.state == "NY" &amp;&amp; form.buildingType == "Sky Scraper") {
              form.addresses = [{
                  addressId: 8,
                  description: "13245 12th Ave"
              },{
                  addressId: 9,
                  description: "345 Park Ave"
              }]
          }
          
          if (form.state == "NY" &amp;&amp; form.buildingType == "Apartment") {
              form.addresses = [{
                  addressId: 10,
                  description: "6668 115th St"
              },{
                  addressId: 11,
                  description: "2839 3rd Ave"
              }]
          }
  
      };
  
      form.performAction = function (expr) {
          return function () {
              if (expr == "GetAddresses") {
                  form.GetAddresses($scope.form);
              }
              if (expr == "GetLayouts") {
                  form.GetLayouts($scope.form);
              }
          };
      };
  
      $scope.$watch('form.state', form.performAction('GetAddresses'));
      $scope.$watch('form.buildingType', form.performAction('GetAddresses'));
  
      
      //This could really be thought of as "LayoutController"
      form.layout = {};
      form.layouts = [];
  
      form.GetLayouts = function (form) {
          if (form.addressId == 1)
           form.layouts = ["A", "B", "C", "D"];
          if (form.addressId == 2)
           form.layouts = ["B", "C", "D"];
          if (form.addressId == 3)
           form.layouts = ["A", "D"];
          if (form.addressId == 4)
           form.layouts = ["A", "D"];
          if (form.addressId == 5)
           form.layouts = ["A"];
          if (form.addressId == 6)
           form.layouts = ["D"];
          if (form.addressId == 7)
           form.layouts = ["C", "D"];
          if (form.addressId == 8)
           form.layouts = ["A", "D"];
          if (form.addressId == 9)
           form.layouts = ["A", "B"];
          if (form.addressId == 10)
           form.layouts = ["B", "C", "D"];
          if (form.addressId == 11)
           form.layouts = ["C", "D"];
      };
  
      $scope.$watch('form.addressId', form.performAction('GetLayouts'));
  
  }]);</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"&gt;&lt;/script&gt;
  &lt;div ng-app="formBuilder"&gt;
      &lt;form name="createForm" class="form-horizontal" ng-controller="FormController as form" novalidate&gt;
          &lt;fieldset&gt;
              &lt;legend&gt;Building Type&lt;/legend&gt;
              &lt;select class="form-control" ng-model="form.state" ng-options="state for state in form.states" ng-change="form.GetBuildingTypes(form.state)"&gt;
                  &lt;option value=""&gt;Select a state&lt;/option&gt;
              &lt;/select&gt;
              &lt;select class="form-control" ng-model="form.buildingType" ng-options="buildingType for buildingType in form.buildingTypes" ng-change="form.GetStates(form.buildingType)"&gt;
                  &lt;option value=""&gt;Select a building type&lt;/option&gt;
              &lt;/select&gt;
          &lt;/fieldset&gt;
          
          &lt;fieldset&gt;
              &lt;legend&gt;Specific Address&lt;/legend&gt;
              &lt;select class="form-control" ng-model="form.addressId" ng-options="obj.addressId as obj.description for obj in form.addresses"&gt;
                  &lt;option value=""&gt;Select an address&lt;/option&gt;
              &lt;/select&gt;
          &lt;/fieldset&gt;
          
          &lt;fieldset&gt;
              &lt;legend&gt;Select Room&lt;/legend&gt;
              &lt;select class="form-control" ng-model="form.layout" ng-options="layout for layout in form.layouts"&gt;
                  &lt;option value=""&gt;Select a room&lt;/option&gt;
              &lt;/select&gt;
          &lt;/fieldset&gt;
      &lt;/form&gt;
  &lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>