0

I have been working on a custom input wrapper that adds error text handling among other things. The problem is I cannot reset the model values, from inspecting the scopes the outside scopes get updated on the reset. The inner scope of the directive does not and I am not sure why.

Changeing the ng-model watch in the directive from scope.$watch(ngModel, function() { to scope.$watch('ngModel', function() { causes the reset to work but then the reset does not work when the viewValue is invalid, the reset should work in this case as well.

Am I doing something terribly wrong? Code below reporoduces the problem.

var app = angular.module('app', []);
app.directive('myInput', function() {
  return {
      restrict: "E",
      require: "ngModel",
      template: $('#myInput').html(),
      scope: {
        "ngModel": "=",
        "name": "@",
        "type": "@",
        "label": "@",
        "errorLabel": "@",
        "placeholder": "@"
      },
      link: function(scope, element, attributes, ngModel) {

        scope.$watch('ngModel', function() {
          scope.value = scope.ngModel;
          console.log('got value: ' + scope.value);
        });
        scope.$watch('value', function() {
          if(scope.value) {
            ngModel.$setViewValue(scope.value);
          }
        });
      }
  };
});

app.controller('user', ['$scope', function($scope) {
  $scope.currentUser = {
    email: "[email protected]"
  };
  $scope.resetUser = function() {
    console.log('resetting user');
    console.log($scope.user);
    $scope.user = angular.copy($scope.currentUser);
    console.log($scope.user);
  };
  $scope.submitUser = function(user) {
    console.log('submitting user');
    console.log(user);
  };
  $scope.resetUser();
}]);
.error {
  color: red;
}
.my-input {
  border: 5px solid transparent;
}
.ng-invalid.my-input {
  border: 5px solid red;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.min.js"></script>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <script type="text/html" id="myInput">
    <ng-form name="thisForm">
      <label
        ng-class="{error: thisForm.$invalid}"
        for="{{name}}"
        ng-bind="thisForm.$valid ? label : errorLabel"></label></br>
      <input
        class="my-input"
        name="{{name}}"
        type="{{type}}"
        placeholder="{{placeholder}}"
        ng-model="value"></input>
    </ng-form>
  </script>
  
</head>
<body ng-app="app">
  <div ng-controller="user">
    <ng-form name="userForm">
      <my-input
        type="email"
        ng-model="user.email"
        error-label="Enter a valid Email"
        label="Email"
        placeholder="Enter an Email"
        name="Email"></my-input>
      </br>
      <button ng-click="resetUser()">Reset</button>
      <button ng-click="submitUser(user)" ng-disabled="userForm.$invalid">Submit</button>
    </ng-form>
  </div>
  
</body>
</html>

1 Answer 1

0

If your remaining issue is that your watcher doesn't trigger when your input is invalid (doesn't pass the Angular email test), it's because Angular does not update your model if the input does not pass validation. Please see this issue for comparison.

In any case, I'd recommend using Angular's ngMessages directive to show and hide error messages for an input. It seems like you are trying to build something that's already provided out-of-the-box.

Sign up to request clarification or add additional context in comments.

1 Comment

In this code the reset button resets the model to a valid value, this does not make sense why the reset does not work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.