title: AngularJS ng-model value is lost after custom validation directive is triggered
body: <p>I created a custom validation directive and used it in a form. It can be triggered with no problem, but after the validation is triggered, I found that the model value is just lost. Say I have</p>
  
  <pre><code>ng-model="project.key" 
  </code></pre>
  
  <p>and after validation, <code>project.key</code> doesn't exist in the scope anymore. I think somehow I understood AngularJS wrong and did something wrong.</p>
  
  <p>Code speaks.</p>
  
  <p>Here is my html page:</p>
  
  <pre><code> &lt;div class="container"&gt;
      ...
      &lt;div class="form-group"
              ng-class="{'has-error': form.key.$invalid &amp;&amp; form.key.$dirty}"&gt;
              &lt;label for="key" class="col-sm-2 control-label"&gt;Key&lt;/label&gt;
              &lt;div class="col-sm-10"&gt;
                  &lt;input type="text" class="form-control text-uppercase" name="key"
                      ng-model="project.key" ng-model-options="{ debounce: 700 }"
                      placeholder="unique key used in url"
                      my-uniquekey="vcs.stream.isProjectKeyValid" required /&gt;
                  &lt;div ng-messages="form.key.$error" ng-if="form.key.$dirty"
                      class="help-block"&gt;
                      &lt;div ng-message="required"&gt;Project key is required.&lt;/div&gt;
                      &lt;div ng-message="loading"&gt;Checking if key is valid...&lt;/div&gt;
                      &lt;div ng-message="keyTaken"&gt;Project key already in use, please
                          use another one.&lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
          &lt;/div&gt;
      &lt;div class="col-sm-offset-5 col-sm-10"&gt;
          &lt;br&gt; &lt;a href="#/" class="btn"&gt;Cancel&lt;/a&gt;
          &lt;button ng-click="save()" ng-disabled="form.$invalid"
              class="btn btn-primary"&gt;Save&lt;/button&gt;
          &lt;button ng-click="destroy()" ng-show="project.$key"
              class="btn btn-danger"&gt;Delete&lt;/button&gt;
      &lt;/div&gt;
  &lt;/form&gt;
  </code></pre>
  
  <p></p>
  
  <p>And here's my directive:</p>
  
  <pre><code>    .directive('myUniquekey', function($http) {
          return {
              restrict : 'A',
              require : 'ngModel',
              link : function(scope, elem, attrs, ctrl) {
                  var requestTypeValue = attrs.myUniquekey;
  
                  ctrl.$parsers.unshift(function(viewValue) {
                      // if (viewValue == undefined || viewValue == null
                      // || viewValue == "") {
                      // ctrl.$setValidity('required', false);
                      // } else {
                      // ctrl.$setValidity('required', true);
                      // }
  
                      setAsLoading(true);
                      setAsValid(false);
  
                      $http.get('/prism-cmti/2.1', {
                          params : {
                              requestType : requestTypeValue,
                              projectKey : viewValue.toUpperCase()
                          }
                      }).success(function(data) {
                          var isValid = data.isValid;
                          if (isValid) {
                              setAsLoading(false);
                              setAsValid(true);
  
                          } else {
                              setAsLoading(false);
                              setAsValid(false);
                          }
                      });
  
                      return viewValue;
                  });
  
                  function setAsLoading(bool) {
                      ctrl.$setValidity('loading', !bool);
                  }
  
                  function setAsValid(bool) {
                      ctrl.$setValidity('keyTaken', bool);
                  }
  
              }
          };
      });
  </code></pre>
  
  <p>Here's the controller for the form page:</p>
  
  <pre><code>angular.module('psm3App').controller(
          'ProjectCreateCtrl',
          [ '$scope', '$http', '$routeParams', '$location',
                  function($scope, $http, $routeParams, $location) {
                      $scope.save = function() {
                              $http.post('/prism-cmti/2.1', {requestType:'vcs.stream.addProject', project:$scope.project})
                              .success(function(data) {
                                  $location.path("/");
                              });
                          };
                  }]);
  </code></pre>
  
  <p>Before this bug, somehow I need to handle the required validation in my custom validation directive too, if I don't do it, required validation would go wrong. Now I think of it, maybe the root cause of these two problems is the same: the model value is gone after my directive link function is triggered.</p>
  
  <p>I'm using Angular1.3 Beta 18 BTW.</p>
  
  <p>Any help is appreciated. Thanks in advance. </p>
  
  <p><strong>Update:</strong>
  Followed @ClarkPan's answer, I updated my code to <code>return viewValue</code> in <code>ctrl.$parsers.unshift()</code> immediately, which makes <code>required</code> validation works well now, so I don't need lines below any more.</p>
  
  <pre><code>        // if (viewValue == undefined || viewValue == null
                      // || viewValue == "") {
                      // ctrl.$setValidity('required', false);
                      // } else {
                      // ctrl.$setValidity('required', true);
                      // }
  </code></pre>
  
  <p>But the <code>{{project.key}}</code> still didn't get updated.
  Then I tried to comment out these two lines here:</p>
  
  <pre><code>                    setAsLoading(true);
                      setAsValid(false);
  </code></pre>
  
  <p>Model value <code>{{project.key}}</code> got updated. I know that if any validation fails, the model value will be cleared, but I thought </p>
  
  <pre><code>                      function(data) {
                              var isValid = data.isValid;
                              if (isValid) {
                                  setAsLoading(false);
                                  setAsValid(true);
                              } else {
                                  setAsLoading(false);
                                  setAsValid(false);
                              }
                          }
  </code></pre>
  
  <p>in <code>$http.get(...).success()</code> should be executed in $digest cycle, which means the model value should be updated.</p>
  
  <p>What is wrong?</p>