13

Given a simple html form like this:

<form name="myForm" action="#sent" method="post" ng-app>
   <input name="userPreference1" type="text" ng-model="shipment.userPreference" />
   <input name="userPreference1" type="text" ng-model="shipment.userPreference" />
   <input name="userPreference1" type="text" ng-model="shipment.userPreference" />
... submit input and all the other code...
</form>

I need your help to know how to check on validation time, if at least one of the inputs is empty. The desired validation is the following. The user must complete at least one a preference.

Using jQuery this:

if ( $("input").val() == "" ) {

Works ok, but would like to figure out how to do the same thing using angular.

Thanks so much in advance,

Guillermo

Guillermo
  • 1,493
  • 3
  • 16
  • 35

3 Answers3

29

So the idea is to disable the submit button if all inputs are blank. You can do like this

<form name="myForm" action="#sent" method="post" ng-app>
   <input name="userPreference1" type="text" ng-model="shipment.userPreference1" />
   <input name="userPreference1" type="text" ng-model="shipment.userPreference2" />
   <input name="userPreference1" type="text" ng-model="shipment.userPreference3" />

   <button type="submit" ng-disabled="!(!!shipment.userPreference1 || !!shipment.userPreference2  || !!shipment.userPreference3)">Submit</button>
</form>

!!str is to force to convert str to a boolean value. And both !!null and !!"" are evaluated to be false.

Demo

zs2020
  • 53,766
  • 29
  • 154
  • 219
  • sza, thanks for your answer! The user won't be required to enter all the fields, just one, so because of that I need to check when validating if at least one input was populated. – Guillermo Aug 15 '13 at 20:22
  • @Guillermo Then they should have different model. – zs2020 Aug 15 '13 at 20:23
  • So that means that I need a model for each input, and then in validation time check all of them? If I have 50 inputs, will be a mess... thanks so much for your answer. Did I follow your suggestion correctly? AngularJS is starting to frustrate me – Guillermo Aug 15 '13 at 20:27
  • sza, great! That helps me a lot, I need to figure out now the code to get all the child inputs of the form, and validate one by one if they're empty. If at least one of them is populated, then it will validate to true, if not will validate to false. Thanks so much!! – Guillermo Aug 15 '13 at 20:35
  • Looking at nowhere and burning my last ideas... Does angular provides you with some kind of selector engine to avoid doing the dom manipulation like in the old times? – Guillermo Aug 15 '13 at 20:37
  • 1
    @Guillermo Checkout ng-repeat. Keep in mind, AngularJS is data/model driven, if you want to manipulate the dom in normal case, just think in how to design the data structure. And angularjs will magically change the dom for you. – zs2020 Aug 15 '13 at 20:47
  • You inspire me to be a better programer, but I have no brain today to follow your advice, thanks so much buddy, you helped me a lot :) – Guillermo Aug 15 '13 at 21:00
  • 3
    There's a better way of doing this. On each of your inputs, add ng-required. That will cause your form controller to run validation, then your – Chris Webb Oct 16 '13 at 04:07
  • 1
    You don't need the !!string - just use `!(shipment.userPreference1 || shipment.userPreference2 || shipment.userPreference3)` – marksyzm Feb 09 '15 at 10:53
4

You can set the "required" in the input elements and style / code how you want to handle with $valid of a form. Check out http://dailyjs.com/2013/06/06/angularjs-7/

Mouli
  • 1,621
  • 15
  • 20
  • Mouli, thanks for your answer, I know it's weird, but in the original state, the user will see three inputs, and will be required to fill at least one, but not all of them. So that's why I think that adding required won't fit for me. I need some equivalent of $("input").val() == "" applied to angularjs. Thanks!! – Guillermo Aug 15 '13 at 20:25
4

My solution was the following:

        $scope.requiredInputsGroup = function () {
            var isRequired = true;
            if (!$scope.shipment) {
                return true;
            }
            angular.forEach(["userPreference1", "userPreference2", "userPreference3"], function (input) {
                if ($scope.shipment[input]) {
                    isRequired = false;
                    return false;
                }
            });

            return isRequired;
        };

You apply that method to a data-ng-required in each of the inputs...

<form name="myForm" action="#sent" method="post" ng-app>
   <input name="userPreference1" type="text" ng-model="shipment.userPreference1" ng-required="requiredInputsGroup()" />
   <input name="userPreference2" type="text" ng-model="shipment.userPreference2" ng-required="requiredInputsGroup()" />
   <input name="userPreference3" type="text" ng-model="shipment.userPreference3" ng-required="requiredInputsGroup()" />

   <button type="submit" ng-disabled="myForm.$invalid">Submit</button>
</form>

And the last bit I applied was to make the button disabled with a simple myForm.$invalid

marksyzm
  • 5,281
  • 2
  • 29
  • 27
  • 1
    Great solution! I altered it so you can pass in the model you are testing against instead of passing an array into the forEach. The only problem was testing against checkboxes which return an 'N' when not checked, but that was really easy to check for in the if. Thanks! – Yeysides Jul 15 '15 at 13:24