diff --git a/ang/form_processor/FormProcessorEditCtrl.js b/ang/form_processor/FormProcessorEditCtrl.js
index 1cda80a900b70b1185d760f1781a7f7d16f56039..2a3761f25b4d9517d7482ae7b3dcff0f43a61fd7 100644
--- a/ang/form_processor/FormProcessorEditCtrl.js
+++ b/ang/form_processor/FormProcessorEditCtrl.js
@@ -39,28 +39,14 @@
     }
   );
   
-  angular.module('form_processor').controller('FormProcessorEditCtrl', function($scope, dialogService, crmApi, apiCalls, $q, $timeout) {
+  angular.module('form_processor').controller('FormProcessorEditCtrl', function($scope, formProcessorFactory, dialogService, crmApi, apiCalls, $q, $timeout) {
   	var ts = $scope.ts = CRM.ts(null);
 
     $scope.formProcessor = apiCalls.formProcessor;
     $scope.locks = {name: true};
     $scope.isNameValid = false;
     $scope.new_id = -1;
-    
-    $scope.inputTypes = CRM.form_processor.inputTypes;
-    for(var i=0; i<$scope.inputTypes.length; i++) {
-    	if ($scope.inputTypes[i].description) {
-    		$scope.inputTypes[i].description = $sce.trustAsHtml($scope.inputTypes[i].description);
-    	}
-    }
     $scope.deletedInputs = [];
-    
-    $scope.actionTypes = CRM.form_processor.actionTypes;
-    for(var i=0; i<$scope.actionTypes.length; i++) {
-    	if ($scope.actionTypes[i].description) {
-    		$scope.actionTypes[i].description = $sce.trustAsHtml($scope.actionTypes[i].description);
-    	}
-    }
     $scope.deletedActions = [];
     $scope.deletedDefaultDataActions = [];
     
@@ -170,57 +156,6 @@
       });
     };
     
-    $scope.removeInput = function removeInput(input) {
-    	var index = $scope.formProcessor.inputs.indexOf(input);
-    	if (index >= 0) {
-    		$scope.formProcessor.inputs.splice(index, 1);
-    		$scope.deletedInputs.push(input);
-    	}
-    	
-    	$scope.editFormProcessorForm.$setDirty();
-    };
-    
-     // Open a dialog for adding an input
-    $scope.addInput = function addInput(inputType) {
-    	if (!inputType) {
-    		return;
-    	}    	    	
-    	var input = {
-    		'id': $scope.new_id,
-    		'type': angular.copy(inputType),
-      	'name': '',
-  			'is_required': 0,
-  			'default_value': '',
-  			'validators': []
-    	};
-      $scope.editInput(input);
-    };
-    
-    // Open a dialog for editting an input
-    $scope.editInput = function editInput(input) {    	    	
-      var options = CRM.utils.adjustDialogDefaults({
-        autoOpen: false,
-        width: '40%',
-        height: 'auto',
-        title: ts('Edit input')
-      });
-      index = $scope.formProcessor.inputs.indexOf(input);
-      var model = {
-      	formProcessor: $scope.formProcessor,
-      	input: input
-      };
-      dialogService.open('InputDialog', '~/form_processor/InputDialogCtrl.html', model, options)
-      .then(function(data) {
-      	$scope.editFormProcessorForm.$setDirty();
-      	if (index >= 0) {
-      		$scope.formProcessor.inputs[index] = data.input;
-      	} else if ($scope.new_id == data.input.id) {
-					$scope.formProcessor.inputs.push(data.input);
-					$scope.new_id --;
-				}
-			});
-    };
-    
     $scope.editOutputHandler = function editOutputHandler() {
     	var options = CRM.utils.adjustDialogDefaults({
         autoOpen: false,
diff --git a/ang/form_processor/FormProcessorEditCtrl/InputTable.html b/ang/form_processor/FormProcessorEditCtrl/InputTable.html
index 9a5567c5771d1f8d19508503f37cd6fb5d56dcb6..22b547b262e33e3957ca9b9c7faca53ab6d2712d 100644
--- a/ang/form_processor/FormProcessorEditCtrl/InputTable.html
+++ b/ang/form_processor/FormProcessorEditCtrl/InputTable.html
@@ -1,54 +1,6 @@
-<!--
-Controller: FormProcessorCtrl
-Required vars: formProcessor
--->
-<div class="crm-block" ng-form="formProcessorInputsForm" crm-ui-id-scope>
-	<h3>{{ts('Inputs')}}</h3>
-<table>
-  <thead>
-	  <tr>
-	    <th>{{ts('Name')}}</th>
-	    <th>{{ts('Type')}}</th>
-	    <th>{{ts('Is required')}}</th>
-	    <th>{{ts('Default value')}}</th>
-	    <th>{{ts('Validation')}}</th>
-	    <th></th>
-	  </tr>
-  </thead>
-  <tbody>
-	  <tr ng-repeat="input in formProcessor.inputs | orderBy:'name'" ng-class-even="'crm-entity even-row even'" ng-class-odd="'crm-entity odd-row odd'">
-	    <td>{{input.name}}</td>
-	    <td>{{input.type.label}}</td>
-	    <td>{{input.is_required == 1 ? ts('Yes') : ts('No')}}</td>
-	    <td>{{input.default_value}}</td>
-	    <td>
-	    	<ul>
-		    	<li ng-repeat="validator in input.validators | orderBy:'validator.label'">
-		    		{{validator.validator.label}}
-		    	</li>
-	    	</ul>
-	    </td>
-	    <td>
-	      <a crm-icon="fa-edit" class="crm-hover-button" ng-click="editInput(input)" title="{{ts('Edit')}}">{{ts('Edit')}}</a>
-	      <a crm-icon="fa-trash" class="crm-hover-button" ng-click="removeInput(input)" title="{{ts('Remove')}}">{{ts('Remove')}}</a>
-	    </td>
-	  </tr>
-  </tbody>
-
-  <tfoot>
-	  <tr class="addRow">
-	    <td colspan="4">
-	    	<select
-        crm-ui-id="formProcessorInputsForm.type"
-        name="type"
-        ui-jq="select2"
-        ui-options="{dropdownAutoWidth : true, allowClear: true}"
-        ng-model="inputType"
-        ng-options="inputType.label for inputType in inputTypes">
-        <option value="">{{ts('- Select input type -')}}</option>
-      </select>
-      <button crm-icon="fa-check" ng-click="addInput(inputType)">{{ts('Add input')}}</button>	    	
-	    </td>
-	  </tr>
-  </tfoot>
-</table>
\ No newline at end of file
+<crm-form-processor-inputs
+	form-processor="formProcessor"
+	inputs="formProcessor.inputs"
+	deletedActions="deletedInputs"
+	entity="FormProcessorInput">
+</crm-form-processor-inputs>
\ No newline at end of file
diff --git a/ang/form_processor/actions/ActionDialogCtrl.html b/ang/form_processor/actions/ActionDialogCtrl.html
index d06941abf867ba60c55e348c3b24fe4bf4d39d41..b191d378296681d4d8d12760f2d76fe61e30e7a7 100644
--- a/ang/form_processor/actions/ActionDialogCtrl.html
+++ b/ang/form_processor/actions/ActionDialogCtrl.html
@@ -1,50 +1,52 @@
-<div ng-controller="ActionDialogCtrl" class="crm-block crm-form-block">
+<div ng-controller="ActionDialogCtrl">
   <div class="crm-block crm-form-block" ng-form="ActionForm" crm-ui-id-scope>
-    <div class="crm-group">
     	
-    	<div crm-ui-field="{name: 'ActionForm.type', title: ts('Type')}">
-    		<div>{{action.type.title}}</div>
-  		</div>
-    	
-    	<div crm-ui-field="{name: 'ActionForm.title', title: ts('Title'), required: true}">
-      <input
-        crm-ui-id="addActionForm.title"
-        type="text"
-        name="title"
-        ng-model="action.title"
-        class="big crm-form-text"
-        required
-        autofocus
-        />
-	    </div>
-	    
-	    <div crm-ui-field="{name: 'ActionForm.name', title: ts('Name'), required: true}">
-      <input
-        crm-ui-id="addActionForm.name"
-        type="text"
-        name="name"
-        ng-model="action.name"
-        ng-disabled="locks.name"
-        required
-        class="big crm-form-text"/>
+  	<div crm-ui-field="{name: 'ActionForm.type', title: ts('Type')}">
+  		<div>{{action.type.title}}</div>
+		</div>
+  	
+  	<div crm-ui-field="{name: 'ActionForm.title', title: ts('Title'), required: true}">
+    <input
+      crm-ui-id="addActionForm.title"
+      type="text"
+      name="title"
+      ng-model="action.title"
+      class="big crm-form-text"
+      required
+      autofocus
+      />
+    </div>
+    
+    <div crm-ui-field="{name: 'ActionForm.name', title: ts('Name'), required: true}">
+    <input
+      crm-ui-id="addActionForm.name"
+      type="text"
+      name="name"
+      ng-model="action.name"
+      ng-disabled="locks.name"
+      required
+      class="big crm-form-text"/>
 
-      	<a crm-ui-lock binding="locks.name"></a>
-      	
-      	<div ng-show="!isValidName(action.name) || !isNameValid">
-        	<em>{{ts('WARNING: The name includes invalid characters or is already in use by another action.')}}</em>
-      	</div>
-	    </div>
-	    
-	    <crm-ap-action-configuration 
-	    	configuration="action.configuration" 
-	    	action="action.type"
-	    	fields="model.fields"
-	    	mapping="action.mapping"
-    	></crm-ap-action-configuration>
+    	<a crm-ui-lock binding="locks.name"></a>
+    	
+    	<div ng-show="!isValidName(action.name) || !isNameValid">
+      	<em>{{ts('WARNING: The name includes invalid characters or is already in use by another action.')}}</em>
+    	</div>
+    </div>
+    
+    <crm-ap-action-configuration 
+    	configuration="action.configuration" 
+    	action="action.type"
+    	fields="model.fields"
+    	mapping="action.mapping">
+  	</crm-ap-action-configuration>
 
+  </div>
+  
+  <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
+		<div class="ui-dialog-buttonset">
 			<button crm-icon="fa-check" ng-click="saveClick()" ng-disabled="ActionForm.$invalid">{{ts('Save and close')}}</button>
 			<button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button>
-			
-    </div>
-  </div>
+		</div>
+	</div>
 </div>
diff --git a/ang/form_processor/actions/crmFormProcessorActions.js b/ang/form_processor/actions/crmFormProcessorActions.js
index c1656444bf125d3cf068f4ec8010a267772e76fe..1edfdfbedac09e34422f256153cf6c334c5d0363 100644
--- a/ang/form_processor/actions/crmFormProcessorActions.js
+++ b/ang/form_processor/actions/crmFormProcessorActions.js
@@ -34,6 +34,7 @@
 		    		$scope.actions.splice(index, 1);
 		    		$scope.deletedActions.push(action);
 		    	}
+		    	$scope.formProcessorActionsForm.$setDirty();
 		    };
 		  
 		   	// Open a dialog for adding an action
diff --git a/ang/form_processor/InputDialogCtrl.html b/ang/form_processor/inputs/InputDialogCtrl.html
similarity index 71%
rename from ang/form_processor/InputDialogCtrl.html
rename to ang/form_processor/inputs/InputDialogCtrl.html
index 51a16e1ee7df9e7fdb7b1e60a5e37e53caba3b69..6da944e63df96351b15b247795fad4c425f65256 100644
--- a/ang/form_processor/InputDialogCtrl.html
+++ b/ang/form_processor/inputs/InputDialogCtrl.html
@@ -1,8 +1,7 @@
-<div ng-controller="InputDialogCtrl" class="">
-  <div class="crm-block" ng-form="InputForm" crm-ui-id-scope>
-    <div class="crm-group">
+<div ng-controller="InputDialogCtrl">
+	<div class="crm-group crm-block crm-form-block" ng-form="InputForm" crm-ui-id-scope>
     	
-    	<div crm-ui-field="{name: 'formProcessorDetailForm.type', title: ts('Type')}">
+    	<div crm-ui-field="{name: 'InputForm.type', title: ts('Type')}">
     		<div>{{input.type.label}}</div>
   		</div>
     	
@@ -17,10 +16,10 @@
         autofocus
         />
         <div ng-show="invalidName">
-        	<em>{{ts('WARNING: The name of the formprocessor is invalid (Only lowercase characters and _ are allowed).')}}</em>
+        	<em>{{ts('WARNING: The name of the input is invalid (Only lowercase characters and _ are allowed).')}}</em>
       	</div>
       	<div ng-show="nameExists">
-        	<em>{{ts('WARNING: The name of the formprocessor already exists.')}}</em>
+        	<em>{{ts('WARNING: The name of the input already exists.')}}</em>
       	</div>
 	    </div>
 	
@@ -42,7 +41,7 @@
 	    	type=input.type
     	></crm-form-processor-type-configuration>
     	
-    	<div class="crm-block" ng-form="InputForm" crm-ui-id-scope>
+    	<div class="crm-block">
     		<div class="crm-group">
 	    		<h2>{{ts('Validation')}}</h2>
     			<select
@@ -67,14 +66,11 @@
      		<crm-form-processor-validation-configuration validator=validator></crm-form-processor-validation-configuration>
      		</div>
      </div>
-    	
-			<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
-				<div class="ui-dialog-buttonset">
-					<button crm-icon="fa-check" ng-click="saveClick()" ng-disabled="InputForm.$invalid">{{ts('Save and Close')}}</button>
-					<button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button>
-				</div>
-			</div>
-			
-    </div>
-  </div>
+  </div>  	
+	<div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
+		<div class="ui-dialog-buttonset">
+			<button crm-icon="fa-check" ng-click="saveClick()" ng-disabled="InputForm.$invalid">{{ts('Save and Close')}}</button>
+			<button crm-icon="fa-times" ng-click="cancelClick()">{{ts('Cancel')}}</button>
+		</div>
+	</div>
 </div>
diff --git a/ang/form_processor/InputDialogCtrl.js b/ang/form_processor/inputs/InputDialogCtrl.js
similarity index 94%
rename from ang/form_processor/InputDialogCtrl.js
rename to ang/form_processor/inputs/InputDialogCtrl.js
index 99c158ccbe8a8004aaa641ded951ed93d6873804..01191e8226891913339237c263d473f617d356e8 100644
--- a/ang/form_processor/InputDialogCtrl.js
+++ b/ang/form_processor/inputs/InputDialogCtrl.js
@@ -12,7 +12,7 @@
     	$scope.nameExists = false;
     	if (newName && !$scope.invalidName) {
     		// Check whether the name already exists
-    		angular.forEach($scope.model.formProcessor.inputs, function(input, key) {
+    		angular.forEach($scope.model.inputs, function(input, key) {
     			if (input != $scope.model.input && input.name == newName) {
     				$scope.nameExists = true;
     			}
diff --git a/ang/form_processor/inputs/crmFormProcessorInputs.html b/ang/form_processor/inputs/crmFormProcessorInputs.html
new file mode 100644
index 0000000000000000000000000000000000000000..88ca22612d5351dcff2b2db674b5183cf658045a
--- /dev/null
+++ b/ang/form_processor/inputs/crmFormProcessorInputs.html
@@ -0,0 +1,50 @@
+<div class="crm-block" ng-form="formProcessorInputsForm" crm-ui-id-scope>
+	<h3>{{ts('Inputs')}}</h3>
+<table>
+  <thead>
+	  <tr>
+	    <th>{{ts('Name')}}</th>
+	    <th>{{ts('Type')}}</th>
+	    <th>{{ts('Is required')}}</th>
+	    <th>{{ts('Default value')}}</th>
+	    <th>{{ts('Validation')}}</th>
+	    <th></th>
+	  </tr>
+  </thead>
+  <tbody>
+	  <tr ng-repeat="input in inputs | orderBy:'name'" ng-class-even="'crm-entity even-row even'" ng-class-odd="'crm-entity odd-row odd'">
+	    <td>{{input.name}}</td>
+	    <td>{{input.type.label}}</td>
+	    <td>{{input.is_required == 1 ? ts('Yes') : ts('No')}}</td>
+	    <td>{{input.default_value}}</td>
+	    <td>
+	    	<ul>
+		    	<li ng-repeat="validator in input.validators | orderBy:'validator.label'">
+		    		{{validator.validator.label}}
+		    	</li>
+	    	</ul>
+	    </td>
+	    <td>
+	      <a crm-icon="fa-edit" class="crm-hover-button" ng-click="editInput(input)" title="{{ts('Edit')}}">{{ts('Edit')}}</a>
+	      <a crm-icon="fa-trash" class="crm-hover-button" ng-click="removeInput(input)" title="{{ts('Remove')}}">{{ts('Remove')}}</a>
+	    </td>
+	  </tr>
+  </tbody>
+
+  <tfoot>
+	  <tr class="addRow">
+	    <td colspan="4">
+	    	<select
+        crm-ui-id="formProcessorInputsForm.type"
+        name="type"
+        ui-jq="select2"
+        ui-options="{dropdownAutoWidth : true, allowClear: true}"
+        ng-model="inputType"
+        ng-options="inputType.label for inputType in inputTypes">
+        <option value="">{{ts('- Select input type -')}}</option>
+      </select>
+      <button crm-icon="fa-check" ng-click="addInput(inputType)">{{ts('Add input')}}</button>	    	
+	    </td>
+	  </tr>
+  </tfoot>
+</table>
\ No newline at end of file
diff --git a/ang/form_processor/inputs/crmFormProcessorInputs.js b/ang/form_processor/inputs/crmFormProcessorInputs.js
new file mode 100644
index 0000000000000000000000000000000000000000..8dffb8cbb815a5447b963c3cacf8403837e103a0
--- /dev/null
+++ b/ang/form_processor/inputs/crmFormProcessorInputs.js
@@ -0,0 +1,80 @@
+(function(angular, $, _) {
+	
+	angular.module('form_processor').directive('crmFormProcessorInputs', function(formProcessorFactory, dialogService, $timeout) {
+	  return {
+	    restrict: 'E',
+	    scope: {
+	      inputs: '=',
+	      formProcessor: '=',
+	      deletedInputs: '=',
+	      entity: '@',
+	    },
+	    templateUrl: '~/form_processor/inputs/crmFormProcessorInputs.html',
+	    link: function($scope, element, attrs){
+	    	$scope.ts = CRM.ts(null);
+	    	
+	    	$scope.new_id = -1;
+	    	
+	    	$scope.inputTypes = angular.copy(CRM.form_processor.inputTypes);
+			  for(var i=0; i<$scope.inputTypes.length; i++) {
+			  	if ($scope.inputTypes[i].description) {
+			  		$scope.inputTypes[i].description = $sce.trustAsHtml($scope.inputTypes[i].description);
+			  	}
+			  }
+	    	
+	    	$scope.removeInput = function removeInput(input) {
+		    	var index = $scope.inputs.indexOf(input);
+		    	if (index >= 0) {
+		    		$scope.inputs.splice(index, 1);
+		    		$scope.deletedInputs.push(input);
+		    	}
+		    	$scope.formProcessorInputsForm.$setDirty();
+		    };
+		    
+		     // Open a dialog for adding an input
+		    $scope.addInput = function addInput(inputType) {
+		    	if (!inputType) {
+		    		return;
+		    	}    	    	
+		    	var input = {
+		    		'id': $scope.new_id,
+		    		'type': angular.copy(inputType),
+		      	'name': '',
+		  			'is_required': 0,
+		  			'default_value': '',
+		  			'validators': []
+		    	};
+		      $scope.editInput(input);
+		    };
+		    
+		    // Open a dialog for editting an input
+		    $scope.editInput = function editInput(input) {    	    	
+		      var options = CRM.utils.adjustDialogDefaults({
+		        autoOpen: false,
+		        width: '40%',
+		        height: 'auto',
+		        title: ts('Edit input')
+		      });
+		      index = $scope.inputs.indexOf(input);
+		      var model = {
+		      	formProcessor: $scope.formProcessor,
+		      	input: input,
+		      	entity: $scope.entity
+		      };
+		      dialogService.open('InputDialog', '~/form_processor/inputs/InputDialogCtrl.html', model, options)
+		      .then(function(data) {
+		      	$scope.formProcessorInputsForm.$setDirty();
+		      	if (index >= 0) {
+		      		$scope.inputs[index] = data.input;
+		      	} else if ($scope.new_id == data.input.id) {
+							$scope.inputs.push(data.input);
+							$scope.new_id --;
+						}
+					});
+		    };
+	    	
+	    }
+	  };
+	});
+	
+})(angular, CRM.$, CRM._);
\ No newline at end of file