title: Angular - Requiring ngModel and using it in controller of custom directive, not link function
body: <p>Can anybody tell me if it's possible to require and use ngModel inside the controller of a custom Angular directive. I'm trying to stay away from the link function. I see most examples use the link function but I'm thinking there must be some way to use it inside a directive controller? Or is it only accessible in a link function? The one way I have seen to do it, as show below, gives me undefined. I'm not sure if there is another way?? I'm trying to validate the component and have the invalid class be set on the error object.</p>
  
  <pre><code>//directive
  angular.module('myApp', [])
    .directive('validator', function (){
      return {
        restrict: 'E',
        require: {
             ngModelCtrl: 'ngModel',
             formCtrl: '?^form'
        },
        replace: true,
        templateUrl: 'view.html',
        scope: {},
        controllerAs: 'ctrl',
        bindToController: {
           rows: '=',
           onSelected: '&amp;?' //passsed selected row outside component
           typedText: '&amp;?' //text typed into input passed outside so developer can create a custom filter, overriding the auto
           textFiltered: '@?' //text return from the custom filter
           ngRequired: "=?" //default false, when set to true the component needs to validate that something was selected on blur. The selection is not put into the input element all the time so it can't validate based on whether or not something is in the input element itself. I need to validate inside the controller where I can see if 'this.ngModel' (selectedRow - not passed through scope) is undefined or not.
        },
        controller: ["$scope", "$element", function ($scope, $element){
           var ctrl = this;
           ctrl.rowWasSelected;
  
           //called when a user clicks the dropdown to select an item
            ctrl.rowSelected = function (row){
                 ctrl.rowWasSelected = true;
                 ctrl.searchText = row.name; //place the name property of the dropdown data into ng-model in the input element
            }
  
           ctrl.$onInit = $onInit;
           function $onInit (){
               ctrl.ngModelCtrl.$validators.invalidInput = validate;            
            }
  
          function validate (modelValue, viewValue) {
               var inputField = ctrl.formCtrl.name;
               var ddField = ctrl.formCtrl.listData;
  
               inputField.$setValidity('invalidInput', ddField.$touched &amp;&amp; ctrl.rowWasSelected);
  
              return true;
            }          
         }];
     }
  });
  
  //template
  &lt;form name="validatorForm" novalidate&gt;
    &lt;div class="form-group" ng-class="{ng-invalid:validatorForm.name.$error.invalid}"&gt;
       &lt;label for="name"&gt;Names&lt;/label&gt;
       &lt;input type="name" class="form-control" name="name" placeholder="Your name" ng-change="typedText(text)" ng-model="ctrl.textFiltered" ng-blur="ctrl.validate()" ng-required="ctrl.ngRequired"&gt;
    &lt;/div&gt;
    &lt;ul ng-show="show list as toggled on and off" name="listData" required&gt;
      &lt;li ng-repeat="row in ctrl.rows" ng-click="ctrl.rowSelected({selected: row}) filterBy:'ctrl.textFiltered' ng-class="{'active':row === ctrl.ngModel}"&gt;{{row}}&lt;li&gt;
    &lt;/ul&gt;
  &lt;/form&gt;
  
  //html
  &lt;validator
     rows="[{name:'tim', city:'town', state:'state', zip: 34343}]"
     on-selected="ctrl.doSomethingWithSelectedRow(selected)"
     typed-text="ctrl.manualFilter(text)"
     text-filtered="ctrl.textReturnedFromManualFilter"
     ng-required="true"&gt;
  &lt;/validator&gt;
  </code></pre>