<!DOCTYPE html>
<html ng-app="textControlsApp" ng-controller="AppCtrl">

  <head>
    <link data-require="bootstrap-css@3.3.1" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script src="https://code.angularjs.org/1.4.3/angular.js" data-semver="1.4.3" data-require="angular.js@1.4.3"></script>
    <script src="simple-controller.js"></script>
    <!-- Note no custom styles, only Bootstrap CSS -->
  </head>

  <body>
    <div class="container">
      <header class="row">
        <h1 class="col-sm-12">Text Fields in Angular and Bootstrap</h1>
        <p class="col-sm-12">Text field valiation and styling using AngularJS and Bootstrap.</p>
      </header>
      
      <!-- blue panel with bound values after data entry -->
      <section class="row panel-body bg-primary">
        <div class="col-sm-12">
          <h4>Field values from model-binding</h4>
          <div class="row">
            <span class="col-xs-6">No validation:</span>
            <span class="col-xs-6">{{model.novalidation}}</span>
          </div>
          <div class="row">
            <span class="col-xs-6">Required, updates on blur:</span>
            <span class="col-xs-6">{{model.requiredmaxtwenty}}</span>
          </div>
          <div class="row">
            <span class="col-xs-6">Required, updates immediately:</span>
            <span class="col-xs-6">{{model.requiredimmediate}}</span>
          </div>
        </div>
      </section>
    
      <!-- Form with input field examples, submit handled by controller function -->
      <form role="form" name="form.test" id="form.test" novalidate class="col-sm-12">
        
        <p class="row col-sm-12">Enter values in the fields to see them appear above.</p>
        
        <!-- different status indications bound to the model, only one shows -->
        <div class="panel">
          <div class="panel-body bg-info" ng-show='model.formstatus === "unsubmitted"'>Form not yet submitted</div>
          <div class="panel-body bg-success" ng-show='model.formstatus === "valid"'>Valid form data submitted</div>
          <div class="panel-body bg-warning" ng-show='model.formstatus === "invalid"'>Invalid form data submitted</div>
        </div>
        
        <!-- Text input, no validation, icons, messages -->
        <div class="form-group">
            <label for="textfield" class="control-label">Text field, no validation</label>
            <input type="text" id="novalidation" name="novalidation" 
                   class="form-control" placeholder="Any or no text is fine" 
                   ng-model="model.novalidation">
        </div>
        
        <!-- Text input, max 20 chars, validates/updates on blur away from field -->
        <div class="form-group has-feedback"
             ng-class="{ 'has-error' : form.test.requiredmaxtwenty.$invalid && !form.test.requiredmaxtwenty.$pristine,
                         'has-success' : form.test.requiredmaxtwenty.$valid && !form.test.requiredmaxtwenty.$pristine }">
          <label for="requiredmaxtwenty" 
                 class="control-label">Text field, required, max 20 chars, updates on blur</label>

          <input type="text" id="requiredmaxtwenty" name="requiredmaxtwenty" class="form-control"
                 ng-maxlength="20" placeholder="Enter up to 20 characters"
                 required aria-required="true" aria-describedby="requiredmaxtwentyInputStatus"
                 ng-model="model.requiredmaxtwenty" ng-model-options="{ updateOn: 'blur' }">

          <!-- Validation icon at right side of field -->
          <span class="glyphicon form-control-feedback" aria-hidden="true"
                ng-class="{ 'glyphicon-remove' : form.test.requiredmaxtwenty.$invalid && !form.test.requiredmaxtwenty.$pristine,
                            'glyphicon-ok' : form.test.requiredmaxtwenty.$valid && !form.test.requiredmaxtwenty.$pristine }"></span>
          <span id="requiredmaxtwentyInputStatus" class="sr-only">(success)</span>

          <!-- Woof-O-Gram validation message if needed -->
          <p ng-show="form.test.requiredmaxtwenty.$invalid && !form.test.requiredmaxtwenty.$error.maxlength && !form.test.requiredmaxtwenty.$pristine"
             class="help-block">C'mon, you should write something</p>
          <p ng-show="form.test.requiredmaxtwenty.$invalid && form.test.requiredmaxtwenty.$error.maxlength && !form.test.requiredmaxtwenty.$pristine"
             class="help-block">That's an awful lot of typing just now.</p>
        </div>
        
        <!-- Text input with input group validates/updates immediately -->
        <div class="form-group has-feedback"
             ng-class="{ 'has-error' : form.test.requiredimmediate.$invalid && !form.test.requiredimmediate.$pristine,
                         'has-success' : form.test.requiredimmediate.$valid && !form.test.requiredimmediate.$pristine }">
          <label for="requiredimmediate" 
                 class="control-label">Text field, required, input group, updates immediately</label>
          
          <div class="input-group">
            <span class="input-group-addon"><span class="glyphicon glyphicon-asterisk"></span></span>
            <input type="text" id="requiredimmediate" name="requiredimmediate" class="form-control"
                 placeholder="Please type something here"
                 required aria-required="true" aria-describedby="requiredimmediateInputStatus"
                 ng-model="model.requiredimmediate">
          </div>

          <!-- Validation icon at right side of field -->
          <span class="glyphicon form-control-feedback" aria-hidden="true"
                ng-class="{ 'glyphicon-remove' : form.test.requiredimmediate.$invalid && !form.test.requiredimmediate.$pristine,
                            'glyphicon-ok' : form.test.requiredimmediate.$valid && !form.test.requiredimmediate.$pristine }"></span>
          <span id="requiredimmediateInputStatus" class="sr-only">(success)</span>

          <!-- Woof-O-Gram validation message if needed -->
          <p ng-show="form.test.requiredimmediate.$invalid && !form.test.requiredimmediate.$error.maxlength && !form.test.requiredimmediate.$pristine"
             class="help-block">If you don't write something I'll be sad</p>
        </div>
        
        <div class="form-group">
          <button type="submit" ng-click='submitForm()' class="btn btn-primary">Submit</button>
          <button type="cancel" ng-click='clearForm()' class="btn btn-default">Clear</button>
        </div>
      </form>
    </div>
  </body>

</html>
// Simple AngularJS controller for text field validation example

angular.module('textControlsApp', [ ])

  // only the one controller in this little example
  .controller('AppCtrl', ['$scope', function($scope) {
    
    // Page data model, initially blank ('pristine') with our own status tracking
    $scope.model = { 
      novalidation: '',                 // text field without validation
      requiredmaxtwenty: '',            // text field, required, max 20 chars
      requiredimmediate: '',            // text field updates immediately
      formstatus: 'unsubmitted'         // status display
    };
    
    // Declare a reference to the form, which will be 'form.test' on the page
    $scope.form = { };
    
    // We don't actually submit this form anywhere, we just test validity
    // and report back.
    $scope.submitForm = function() {
      if ($scope.form.test.$valid) {
        $scope.model.formstatus = "valid";    // that was a happy form  
      } else {
        $scope.model.formstatus = "invalid";  // sad trombone
      }
    };
    
    // Form clear function
    $scope.clearForm = function() {
      // clear the fields
      $scope.model.novalidation = '';
      $scope.model.requiredmaxtwenty = '';
      $scope.model.requiredimmediate = '';
      // reset our internal state
      $scope.model.formstatus = 'unsubmitted';
      // reset the field validation for the form
      $scope.form.test.$setPristine();
    };
}]);

Angular JS & Bootstrap Form Text Fields
=======================================

Examples of form text fields formatted with Bootstrap, with form submit
state tracked in a simple controller. Model binding, validation messages and
validation icons are included.