JSFiddle - React, Tailwind, and code Playground

HTML

<div ng-app="myApp" ng-controller="MyController">
    <my-form config="config"></my-form>
</div>

CSS

.cbay_form_group_error input {
        border: 1px solid #a94442 !important;
    }

JavaScript

angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
  $scope.config = {
    name: 'form1',
    fields: [
      {type: 'text', name: 'field1', model: 'obj.field1'},
      {type: 'text', name: 'field2', model: 'obj.field2'}
    ]
  };
}])
.directive('myForm', ['$compile', function($compile) {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      config: '='
    },
    link: function (scope, iElement, iAttrs, controller) {
      var html = '<form name="{{config.name}}">' +
          '   <my-field ng-repeat="item in config.fields" config="item"></my-field>' +
          '   <button ng-click="submit()">submit</button>' +
          '</form>';
      iElement.append($compile(html)(scope));
      scope.submit = function () {
        var form = scope[scope.config.name];
        if(!form.$valid) {
          angular.forEach(form, function(v, k) {
            if(k[0] == '$') {
              return;
            }
            if(!v.$valid) {
              v.$setDirty(true);
            }
          });
          console.log('form invalid');
          return;
        }
        console.log('valid form can be submitted')
      }
    }
  }
}])
.directive('myField', ['$compile', function($compile) {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      config: '='
    },
    link: function(scope, iElement, iAttrs, controller) {
      var config = scope.config;
      var html = '<div ng-class="{cbay_form_group_error: form1.' + config.name + '.$dirty && form1.' + config.name + '.$invalid}">' + 
      '    <input type="' + config.type + '" ng-model="' + config.model + '" name="' + config.name + '" ng-required="true" />' +
      '</div>';
      iElement.after(html);
      var element = iElement.next();
      iElement.remove();
      $compile(element)(scope.$parent);
    }
  }
}])
        ;