0

I have an angular form as part of a single page App. The 'Continue' button moves a user to the next section of the app, and has an ng-click. I would like to prevent this ng-click from happening when the button is clicked and the form is invalid, but I don't want to disable the Continue button.

Example: A user comes to the page and immediately clicks the Continue button without providing a first name. The error message "You should provide a first name" is shown and the user remains on the page.

How can I do this? Here is the code:

<form name="form" novalidate >

<div ng-show="form.FirstName.$touched && form.FirstName.$error.required" class="errorMessage">
    You must enter a first name
</div>

<div class="form-group">
    <label for="firstName" class="form-label">First Name</label>
    <input id="firstName" class="form-control" name="FirstName" ng-model="vm.user.firstName" required />
</div>

<div class="btn-group">
    <button ng-click="vm.next()">Continue</button>
</div>
</form>
noclist
  • 1,659
  • 2
  • 25
  • 66

2 Answers2

8

Just add form.$valid && before the function call:

<form name="form" novalidate >

<div ng-show="form.FirstName.$touched && form.FirstName.$error.required" class="errorMessage">
    You must enter a first name
</div>

<div class="form-group">
    <label for="firstName" class="form-label">First Name</label>
    <input id="firstName" class="form-control" name="FirstName" ng-model="vm.user.firstName" required />
</div>

<div class="btn-group">
    <button ng-click="form.$valid && vm.next()">Continue</button>
</div>
</form>
Carl Ambroselli
  • 616
  • 6
  • 18
  • Works good, is there a way to show the error messages when clicking the Continue button? – noclist Nov 13 '15 at 15:38
  • Just check if the user already tried: `ng-show="tried && form.FirstName.$touched && form.FirstName.$error.required"` + `ng-click="tried = true; form.$valid && vm.next()"` – Carl Ambroselli Nov 13 '15 at 15:43
  • But since you are now adding a lot of logic to the view you should consider putting it into a controller function. – Carl Ambroselli Nov 13 '15 at 15:44
2

Either a button is disabled or it's clickable, you can't have it both ways.

What you could do in your controller for vm.next() is say:

myApp.controller('Page1Controller'),  ['$scope', function ($scope)
{
    $scope.vm = {};

    $scope.vm.next = function()
    {
        if (! $scope.vm.isFormValid())            
            return;            
        //move to the next page with your current code
        ...
    }

    $scope.vm.isFormValid()
    {
        $scope.vm.shouldShowError = $scope.form.valid; //add vm.shouldShowError to your error message ng-show in the view so it will display only after clicking continue
        return $scope.form.valid;
    }
}]);
Richard
  • 14,798
  • 21
  • 70
  • 103
  • I agree if a button is not supposed to take you to the next page/form/etc. it should appear that way to the user that the button will not work. Best to disable the button using `vm.form.$invalid`. – Sean Larkin Nov 13 '15 at 15:14
  • Do I need to write an isFormValid() function? i figured there might be something built in to angular to determine this. – noclist Nov 13 '15 at 15:20
  • No, you can use only $scope.form.valid. I found in bigger forms I almost always had to do some sort of custom validation so I got into the habit of always including an isValid function for readability. – Richard Nov 13 '15 at 15:36
  • Having trouble defining $scope as I don't currently use it in my controller. – noclist Nov 13 '15 at 15:39
  • Added example controller declaration with $scope to my answer – Richard Nov 13 '15 at 15:46