JSFiddle - React, Tailwind, and code Playground

by kryo

HTML

<body ng-app="testApplication">
  <form name="testForm" ng-controller="formCtrl" form-grade>
    <ul class="grading" ng-if="formMsgs.length > 0">
      <li ng-repeat="item in formMsgs" class="{{item.cls}}">{{item.msg}}</li>
    </ul>
    <dl>
      <dt>Enter something below:</dt>
      <dd>
        <input type="text" ng-model="formEntry.name" required />
        <ul class="grading" ng-if="fieldMsgs.name.length > 0">
          <li ng-repeat="item in fieldMsgs.name" class="{{item.cls}}">{{item.msg}}</li>
        </ul>
      </dd>
    </dl>
    <dl>
      <button ng-click="submit()" ng-disabled="testForm.$invalid">Submit</button>
      <button ng-click="submit()">Submit (overridden)</button>
      <button ng-click="reset()" ng-disabled="isClean()">Reset</button>
    </dl>
    <div class="state">
 <pre>Current entry state: {{formEntry | json}}
-------------------------------------------------
Grade state:
scope.formMsgs: {{formMsgs | json}}
scope.fieldMsgs:   {{fieldMsgs | json}}</pre>
    </div>
  </form>
</body>

SCSS

@import 'compass/reset';

.state {
  padding: 5px 10px;
  margin-top: 10px;
  background-color: silver;
}
dl {
  dt, dd {
    padding: 0;
    margin: 0;
  }
  dt {
    font-weight: bold;
  }
  dd {
  }
}
.grading {
  display: block;
  list-style: none;
  padding: 0;
  margin: 0;

  .info {
    color: green;
  }
  .error {
    color: red;
  }
}

JavaScript

'use strict';

angular.module("testApplication", [])
.config(function(){
})
.factory('pseudoData', function(){
  return {
    post: function(entry){ // this simulates the angular $http post (pretend it's backend).
      var
      valid = ['hans','kryo','jr'],
      param = 'name',
      responseCode = 200,
      response = [];

      if(valid.indexOf(entry[param]) === -1) {
        responseCode = 400; // invalid response code
        response.push({     // simulates the node-validator format
          param: param,
          msg: 'Value must be one of: ' + valid.join(', '),
          value: entry[param]
        });
        response.push({ // add form failure msg
          msg: 'Form submission failed, please check messages.'
        });
      }
      else {
        response.push({ // add field success msg
          param: param,
          msg: 'Good job!',
          value: entry[param]
        });
        response.push({ // add form success msg
          msg: 'Form completed successfully!'
        });
      }

      return {
        then: function(success, error){
          var angularPseudoResponse = {
            config: {},
            data: response,
            headers: function(){},
            status: responseCode
          };
          if(responseCode === 200) {
            success(angularPseudoResponse);  
          }
          else {
            error(angularPseudoResponse);  
          }
          return this;
        }
      };
    }
  };
})
.directive('formGrade', function($compile){
  return {
    restrict: 'A',
    controller: function($scope, $element) {
      var
      gradeTpl = ['<ul class="grade">',
        '<li ng-repeat="item in messages" class="{{item.cls}}">{{item.msg}}</li>',
      '</ul>'].join('');

      function clearGrading() {
        $scope.formMsgs = [];
        $scope.fieldMsgs = {};
      }
      function addFormMsg(msg, cls) {
        $scope.formMsgs.push({
          cls: cls,
          msg: msg
        });
      }
     ...