Some malfunctions in my user task form

Hi to everyone.
I have created an embedded user task form based on the tutorial (Dynamically Add / Remove HTML Input (Form) fields using AngularJS) but there are some malfunctions which I would like to mention here in case anyone could help me of course. :confused:

  1. When my form is loaded in tasklist, it is displayed like in the following screenshot (with 2 table rows):
    image.
    But I would prefer to be displayed with the 2nd table row only.
  2. The user who is assignee for this task form can not submit the form (“Complete” is deactivated when he clicks on it).
  3. If the user selects to save the task form, the submitted values are lost.
  4. I would like to know how a user can see or edit the submitted values from one task form in another one. Are the submitted values saved in my local H2 database ? Do I need to write PHP in order to save the values in a database ?
  5. When I click on the “Add” button in order to generate a new table row, the uploaded file is automatically removed from the previous table row and is added to the next one (like the following screenshot):
    image
    And this happens again and again when I add new rows in my table.
  6. I would like to be able to remove an uploaded file from the file input field by clicking on a “x” element next to the uploaded file (in case I want to upload something different for example).
  7. I would like to increase the width of the 2nd form field (“Brief Description”) and decrease the width of the 4rth form field (“Price”) in my table.
    I also posted my full code snippet (with my comments) here:
<form role="form">
	<script cam-script type="text/form-script">
		var item = $scope.item = [																// Custom JavaScript creates an array of JSON Objects and binds it to the angular $scope of the form as a variable named "item". 
			{ Category: "", BriefDescription: "", DetailedDescription: "", Price: "" }			
		];															                                                        
		$scope.addItem = function () {															// We make a function named "addItem".
			var item = {};																		// We add the new "item" to the Array.
			item.Category = $scope.Category;
			item.BriefDescription = $scope.BriefDescription;
			item.DetailedDescription = $scope.DetailedDescription;
			item.Price = $scope.Price;
			$scope.item.push(item);																// We use the value of the "item" input field to add an item to the array.
			$scope.Category = "";
			$scope.BriefDescription = "";
			$scope.DetailedDescription = "";
			$scope.Price = "";	
		};
		$scope.removeItem = function (index) {													// We make a function named "removeItem". 
			var category = $scope.item[index].Category;											// We find the record using "index" from the Array.					
			$scope.item.splice(index,1);														// We use "index" to remove the "item" from the Array.
		}
		camForm.on('form-loaded', function() {													// We hook into the lifecycle of Camunda SDK JS Form.
			camForm.variableManager.createVariable({											// We create (declare) the process variable named "item" in the "variableManager"  
				name:'item',
				type:'json',																	// and provide as type information 'json' used for serialization.
				value:item
			});
		});
		camForm.on('submit', function(evt) {													// We hook into the lifecycle of Camunda SDK JS Form.
			if (item.length < 1) {																// If no "item" is added,
				evt.submitPrevented = true;														// an event handler prevents the submit from being executed by setting the property "submitPrevented" to "true".
			}
		});
	</script>
	<h2>My List of Items</h2>
	<div>													
		<table>																									<!-- An HTML table is populated from the JSON array "item" using the "ng-repeat" directive. -->
			<tr>																								<!-- Each row of the table consists of 4 HTML Input Form fields and a button. -->
				<th>Category</th>
				<th>Brief Description</th>
				<th>Detailed Description</th>
				<th>Price</th>
				<th></th>
			</tr>
			<tbody ng-repeat="x in item track by $index">														<!-- A "ng-repeat" directive is assigned to the "body section" of the HTML table in order to repeat all the items of the JSON array. -->
				<tr>																							<!-- For each JSON object of the "item" JSON array a "tr" element with 4 HTML Input Form fields and a button is generated and appended into the table. -->
					<td><input type="text" value="{{x.Category}}" /></td>						
					<td><input type="text" value="{{x.BriefDescription}}" /></td>
					<td><input type="file" value="{{x.DetailedDescription}}" /></td>
					<td><input type="text" value="{{x.Price}}" /></td>
					<td><input type="button" ng-click="removeItem($index)" value="Remove" /></td>				<!-- A "ng-click" directive is assigned to the button and calls the function named "removeItem" with the current $index when button is clicked. -->
				</tr>
			</tbody>
			<tfoot>
				<tr>
					<td><input type="text" ng-model="Category" required /></td>
					<td><input type="text" ng-model="BriefDescription" required /></td>
					<td><input type="file" 
							   cam-variable-name="DetailedDescription" 
							   cam-variable-type="File" 
							   cam-max-filesize="10000000" ng-model="DetailedDescription" required /></td>
					<td><input type="text" ng-model="Price" required /></td>
					<td><input type="button" ng-click="addItem()" value="Add" /></td>							<!-- A "ng-click" directive is assigned to the button and calls the function named "addItem" when button is clicked. -->
				</tr>
			</tfoot>
		</table>
	</div>
</form>

I know that it is difficult to have answers in all of these questions but if someone could help me in any of these questions, I would really appreciate it. To tell you the truth, I am in a hurry because I want to complete my the automation of my process for a university project.
Does anyone know if I can find any kind of support here by the Team of Camunda Developpers ?

Thank you in advance.
Steve

Hi @steftriant,

please add your task form code and your BPMN process file.

Cheers
kristin

Hi @steftriant,

I checked your user task form and will try to answer your questions.

1.) You have 2 table rows because you already initialise your first item for the table with:
var item = $scope.item = [{ Category: "", BriefDescription: "", DetailedDescription: "", Price: "" }];
Delete { Category: "", BriefDescription: "", DetailedDescription: "", Price: "" } to fix it.

2.) The “complete” button is disabled because the “required” attribute is set on the file input field.

3.) Be sure that the variable $scope.item contains an item object.

4.) When the user submit the form, the created variable ‘item’ is a process variable and store in the engine tables. You can access this process variable in another user task.

5.) The file is just uploaded when you click on the submit button. You could try to add the “add row” into an own form and to submit the form when clicking on the add button.

6.) Maybe work on it when the other stuff of the form is working.

7.) You can use CSS to adjust the form field witdh.

Cheers
kristin

Hi @kristin and sorry for my delayed response.
First of all, thank you for the interest.
I saw what you wrote, I ran again my process and I have to point out the following:
1.) I deleted what you indicated and is ok now.
2.) I deleted also the “required” attribute from the file input field and is now also ok.
3.) I can’t understand exactly what you mean here. Each “item” is represented by 4 other variables in my task form (Category, Brief Description, Detailed Description, Price) and the user must insert values for all of these variables so as to add a new item in the table.
4.) I will check that when I submit the form in order to see or edit the submitted values in the next user task form of my process.
5.) I can’t understand what you mean by saying “add the ‘add row’ into an own form”. Have I to create another form?
6.) I will try to add a span element “x” for each of the file input field and to give it a ng-click directive (but later as you suggested).
7.) I have inserted an inline style sheet (by adding the “style” attribute in order to apply a unique width for these 2 input form fields (“Brief Description”, “Price”) in the HTML section of my code but as you can see in the following screenshot, the width of the cells didn’t change.


I also uploaded again my whole code (with very slight modifications in comparison to the above one) in case you want to check something and the BPMN file of my whole process diagram. This form corresponds to the first user task in my process.

<form role="form">
	<script cam-script type="text/form-script">
		var item = $scope.item = [];																		// Custom JavaScript creates a JavaScript Object and binds it to the angular $scope of the form as a variable named "item".															                                                        
		$scope.addItem = function () {																		// We make a function named "addItem".
			var item = {};																					// We add a new "item" to the Array.
			item.Category = $scope.Category;
			item.BriefDescription = $scope.BriefDescription;
			item.DetailedDescription = $scope.DetailedDescription;
			item.Price = $scope.Price;
			$scope.item.push(item);																			// We use the value of the "item" input field to add a new "item" to the Array.
			$scope.Category = "";																			// We clear the TextBox "Category".
			$scope.BriefDescription = "";																	// We clear the TextBox "BriefDescription".
			$scope.DetailedDescription = "";																// We clear the TextBox "DetailedDescription".
			$scope.Price = "";																				// We clear the TextBox "Price".
		};
		$scope.removeItem = function (index) {																// We make a function named "removeItem". 					
			var category = $scope.item[index].Category;														// We find the record using "index" from the Array.
			$scope.item.splice(index, 1);																	// We use an index to remove an "item" from the Array.
		}
		camForm.on('form-loaded', function() {																// We hook into the lifecycle of Camunda SDK JS Form.
			camForm.variableManager.createVariable({														// We create (declare) a 'json' variable named 'item' in the "variableManager".  
				name:'item',
				type:'json',																	
				value:item
			});
		});
		camForm.on('submit', function(evt) {																// We hook into the lifecycle of Camunda SDK JS Form.	
			if (item.length<1) {																			// If no item is added, 
				evt.submitPrevented = true;																	// an event handler prevents the submit from being executed by setting the property "submitPrevented" to "true".
			}
		});
	</script>
	<h2>My List of Items</h2>
	<div>													
		<table>																								<!-- An HTML table is populated from the JSON Array "item" using the "ng-repeat" directive. -->
			<tr>																							<!-- Each row of the table consists of 4 HTML Input Form fields and a button. -->
				<th>Category</th>
				<th style="width:350px;">Brief Description</th>
				<th>Detailed Description</th>
				<th style="width:150px;">Price</th>
				<th></th>
			</tr>
			<tbody ng-repeat="x in item track by $index">													<!-- An "ng-repeat" directive is assigned to each row of the table in order to repeat all the "items" of the JSON Array. -->
				<tr>													
					<td><input type="text" value="{{x.Category}}" /></td>						
					<td style="width:350px;"><input type="text" value="{{x.BriefDescription}}" /></td>
					<td><input type="file"
						       cam-variable-name="DetailedDescription"					
						       cam-variable-type="File"
						       cam-max-filesize="10000000" value="{{x.DetailedDescription}}" /></td>
					<td style="width:150px;"><input type="text" value="{{x.Price}}" /></td>
					<td><input type="button" ng-click="removeItem($index)" value="Remove" /></td>			<!-- An "ng-click" directive is assigned to the button and calls the function named "removeItem" with the current "$index" when button is clicked. -->
				</tr>
			</tbody>
			<tfoot>
				<tr>
					<td><input type="text" ng-model="Category" required /></td>
					<td style="width:350px;"><input type="text" ng-model="BriefDescription" required /></td>
					<td><input type="file" 
						       cam-variable-name="DetailedDescription" 
						       cam-variable-type="File" 
						       cam-max-filesize="10000000" ng-model="DetailedDescription" /></td>
					<td style="width:150px;"><input type="text" ng-model="Price" required /></td>
					<td><input type="button" ng-click="addItem()" value="Add" /></td>						<!-- An "ng-click" directive is assigned to the button and calls the function named "addItem" when button is clicked. -->
				</tr>
			</tfoot>
		</table>
	</div>
</form>

For some reason, my code snippet isn’t displayed but @thorben had edited my previous one to display it in this post.

Electronic Equipment Competitions.bpmn (20.5 KB)

Thanks a lot again.

Cheers,
Steve

Hi again @kristin.
In addition, with regards to my 2nd issue with the “required” attribute, I would like to ask if I can do something to prevent the submission of my form in case the user forgets to upload a file. Because now that I have deleted this attribute, the form can be submitted even if without a file. :neutral_face:

Cheers,
Steve

Hey Steve,

See How to format code blocks? for how to format code in this forum.

Cheers,
Thorben

1 Like

Hi @steftriant,

regarding your answer to the follwing points.

3.) First time, I understand it not correctly. Please forget my first answer to this point. The problem is your javascript code. When you add a row, click on save, change the tabs and go back into the “Form” tab, your JS code is executed and a new variable “item” is defined. This means, the variable “item” is empty and you see only an empty table.

5.) You see always the uploaded file removed from the previous table row and added to the next one because the file is not uploaded when you click on the “Add” button. It would be uploaded when you click on the “submit” button. Maybe it is not the best concept to use the table for adding and displaying all rows. Eventually, it could be easier to have a table which displays all added rows and below a form to add a new row.

6.) Maybe it is not working with inline css or you need to define a width for the whole table. I mean, you could play a bit with it to find a solution.

Cheers
kristin

Hi again @kristin.

Thanks for your last response here.

I would like to ask the following:

2.) Is there any way to prevent the submission of my form in case the user forgets to add (upload) a file? Because, now that I have deleted the “required” attribute from the file input field in the HTML section of my code, my form can be submitted even if without an uploaded file which is considered to be mandatory in my scenario.

3.) From what you mentioned, I understand that when a new variable “item” is defined, all the added ones get lost. What do you mean when saying that my variable “item” is empty and what can I do for this (if I can do sth)?

5.) If I understand correctly here, you mean that I could try to separate my “Add” button from the table and to add it in a simple form which can be put below in the same page? And whenever the user adds a new item (by clicking on this button of the form), this item can be automatically displayed in the above table? Would be easy please to upload a similar screenshot because it is not very clear to me?

6.) I also tried to use another way here (by adding an external CSS file in which I defined a unique width for all the

elements of my table) but nothing changed again.

Cheers,
Steven

Hi @steftriant,

2.) You could try to check whether a file is uploaded with $scope.camForm.fields[0].element[0].files[0]. When it is undefined, you can go out from this function or do some other stuff.

  1. I mean, you variable ‘item’ get the default value

var item = $scope.item = [];

  1. Did you try to add an inline style with percentage values? I think, you need to add a width for the whole table (<table style="width: 100%">) and for the columns (<th style="width: 20%;">Brief Description</th>).

Cheers
kristin

Hi again @kristin and thanks for your last response here.

I would like to ask the following:

2.) From your answer here I understand that there isn’t any way to prevent the submission in that case but only to check for uploaded files. So, can you tell me please where can I find details for the usage of the $scope.camForm.fields[0].element[0].files[0]? Because I 've never seen it before in Docs.

3.) Can I do sth in order to overcome the issue with the lost added values of my variable “item”? Always, in case the user selects to save the current state of his form of course. Has to do with my code or sth else?

5.) From your screenshot I understand that I may try to add a form with my 4 input fields and a button to add a new “item”. And I will have to display all the added values in a table above with the possibility to remove a row. Could you please help me a bit with the code or post here a similar code snippet example?

6.) I tried what you mentioned but the only that changes (as you can see in my following screenshot), is the gap between my cells of my rows, not the cells.

Sorry if I bother you with my many questions each time but this is the reason why I had asked here for support by Camunda Team. :confused:

Cheers,
Steven

Hi @steftriant,

I think, it is not the right way to use the task list for this complex scenario. Maybe, it could be better to find out what the goal of your application is? Could you please describe the use case of your process application. A better solution could be to build an own UI which starts the process with the required content.

The problem which I see with your complex form in the tasklist is the following. It should only be possible to complete the task when “items” exists. But this cannot be checked because the “add” form has only the required fields. This means, you have to add an item, fill out the input fields of the “add” form without clicking on the add button and just after that it is possible to click on the complete button… Do you see, what I mean?

Independent of my view, my answers.

  1. I think, there is no documentation.

  2. At the moment, I see no solution.

  3. Please see the uploaded file. test.txt (3.9 KB)

  4. Please try to set the same width configuration to the input field.

Cheers
kristin

Hi @kristin, to everyone else and sorry for my delayed response here.

To begin with your last suggestion here, I have to give you a brief description of my process scenario.

My process concerns the annual procurement of my university.
It begins when my 1st user (the Central Administrator of the university) decides that he needs to configure all the necessary specifications (Category, Brief Description, Detailed Description, Price) for various electronic products. So he has to create and send a list of items to a group of 5 users (5 Local Administrators), every of whom, works independently for his faculty in the same university. So, in my 2nd user task, every user of this group has to select from the preconfigured list of the first user. But, every user has a certain budget to spend for his order and so, in my 3rd task I want to compare the budget of every faculty with the corresponding expected expenses. This comparison is going to be done automatically by a service. Only if the expected expenses of every faculty are covered by their corresponding budget (so I have to compare 5 budgets with 5 expected expenses here), the 1st user (Central Administrator) gathers the list of selected items from each user of the previous group. After, a pdf document with the total specifications (for the whole university) is automatically generated by a service. In the last task of this process, the same user (the 1st one), sends via e-mail this generated pdf document to the procurement department of the university.
In case the expected expenses exceed the budget, the corresponding user (Local Administrator) must select again from the preconfigured list of the 1st user and the comparison has to be done again.

I uploaded again my bpmn process file in case you want to see the diagram.
What do you mean when you say that I may try to build my own UI to start my process with the required content?

Thank you a lot,
Steve

My bpmn process file

Electronic Equipment Competitions.bpmn (20.5 KB)

Steve

Hi @steftriant,

did you get your user task form working like you want? Awesome!

I mean, you could have an UI (html/javascript) which contains the logic of your described user task form in this thread. There, you can add all necessary specifications which describes the item object. After adding all items, you could have a button to send the form and start your process. The item list is the payload when you start the process. The first user task in your process would be Select items.

How do you start the process now? Do you use the tasklist for that?

Cheers
kristin

Hi again @kristin.

If you mean my 1st user task form, it is working like I want. My only issue there has to do with the adding of my files (Detailed Description files) because I don’t know how to check for uploaded files in my form.

As for your suggestion, if I understand correctly you mean that the start event of my process could be the submission of my first form (with the adding of the items in the table). What do you mean when saying “payload” here?

I haven’t got a special event for starting my process. By this I mean that my 1st user starts the process whenever he wants. Yes, I have been loading every written html form from my eclipse in Tasklist.
Is there any other way for my users to work on their tasks except for the Tasklist?

Thank you,
Steve