How to add selected items in a shopping cart using AngularJS?


#1

Hi to everyone.

I have been trying to find a way to implement automatically a task in my process.
This is the 3rd task (Budget Coverage Control) in my diagram.

In this task, I want to make automatically a simple calculation from the previous multi-instance user task (Select items) and to compare 2 values: The calculation result and the Local budget. I want to make this check for 5 different users. So, based on the result of this comparison, I want to take a decision (XOR Gateway in my diagram).

My issue is that I don’t know which type of task (Service or Script) and which method is the most appropriate for my scenario as I am not so experienced.

Could anyone guide me on this please? Is there a similar example on Github or somewhere else which I could advise?

Thank you,
Steve


#2

Deciding what type of task to use depends heavily on how you would like to write you’re business logic.
What you’re trying to achieve is relatively straight forward so you could use a Script Task and write your logic in JavaScript or Groovy. A Service Task can be used to directly attach a Java Class or be called my any other programming language like C# or Python.

There is also might be a possibility to use DMN to make the calculation and thus use a Business Rules task.


#3

Hi again @Nial.

Yes, having compared the 2 types (script and service) of tasks, I think that the script would be more suitable for me. So, I will have to make a search in google to find a way to calculate the total sum of an order list form (using JavaScript or AngularJS) like the one in my following screenshot:

After the calculation of the total sum and the submission of this form, I want from the engine to take one of the 2 possible decisions, based on the comparison between the total sum and one constant number (the XOR gateway in my diagram).

I haven’t seen the Business Rule Task until now. How do you see my thought?

Thanks,
Steve


#4

Hi to all again.

I have the following html table in a task:

I want to write the proper code in order to calculate and display the total sum for the selected items (on checkbox click). Since I select an item I have to fill in the desired quantity.

So, I want to multiply the price by the quantity for each selected item and to add all of the row costs to display the total of my order.

My code is this one:

<form role="form" name="selectForm">
	<script cam-script type="text/form-script">
		camForm.on('form-loaded', function() {																			// The variable 'item' has not been loaded (fetched) from the server yet.
			camForm.variableManager.fetchVariable('item');																// We tell the "Form SDK" to fetch the 'json' variable named 'item'.
		});
		camForm.on('variables-fetched', function() {																	// The variable 'item' has been loaded (fetched) from the server
			$scope.item = camForm.variableManager.variableValue('item');												// and is bound to the current AngularJS $scope of the form.
		});
	</script>
	<h2>My List of Choices</h2>																							
	<div>
		<table style="width:100%;">
			<thead>
				<tr>
					<th style="width:140px;">Category</th>
					<th style="width:305px;">Brief Description</th>
					<th style="width:250px;">Detailed Description</th>
					<th style="width:75px;" >Price</th>
					<th></th>
				</tr>			
			</thead>
			<tbody ng-repeat="x in item track by $index">
				<tr>
					<td><input style="width:140px;" type="text" value="{{x.Category}}" readonly /></td>
					<td><input style="width:305px;" type="text" value="{{x.BriefDescription}}" readonly /></td>
					<td><input style="width:250px;" type="file" value="{{x.DetailedDescription}}" readonly /></td>			
					<td><input style="width:75px;"  type="text" value="{{x.Price}}" readonly /></td>
					<td><input style="width:25px; height:25px;" type="checkbox" ng-model="chkselct"								 					 
							   								    cam-variable-name="isItemSelected"													
							   								    cam-variable-type="Boolean" /></td>
					<td ng-show="chkselct">Quantity: <input style="width:60px;" type="number"
																	   		    cam-variable-name="quantity" min="1"
																	   		    cam-variable-type="Integer" /></td>	
				</tr>
			</tbody>
		</table>
	</div>
</form>

Could anyone help me please?

Thanks in advance,
Steve


#5

Hi to all users.

I 've been struggling to find a way to calculate the total sum of my order list using AngularJS but for the moment I can’t find something. :confused:

Based on an example found in http://plnkr.co/edit/QSxYbgjDjkuSH2s5JBPf?p=preview via stack overflow I edited my above code here and I wrote this one:

<form role="form" name="selectForm">
	<script cam-script type="text/form-script">
		camForm.on('form-loaded', function() {																			// The variable 'item' has not been loaded (fetched) from the server yet.
			camForm.variableManager.fetchVariable('item');																// We tell the "Form SDK" to fetch the 'json' variable named 'item'.
		});
		camForm.on('variables-fetched', function() {																	// The variable 'item' has been loaded (fetched) from the server
			$scope.item = camForm.variableManager.variableValue('item');												// and is bound to the current AngularJS $scope of the form.
		});
		var i = 0;
	</script>
	<h2>My Order List</h2>																							
	<div>
		<table style="width:100%;">
			<thead>
				<tr>
					<th style="width:140px;">Category</th>
					<th style="width:305px;">Brief Description</th>
					<th style="width:250px;">Detailed Description</th>
					<th style="width:75px;" >Price</th>
					<th></th>
					<th>Quantity</th>
					<th>Subtotal</th>
				</tr>			
			</thead>
			<tbody ng-init="total = 0">
				<tr ng-repeat="x in item track by $index">
					<td><input style="width:140px;" type="text" value="{{x.Category}}" readonly /></td>
					<td><input style="width:305px;" type="text" value="{{x.BriefDescription}}" readonly /></td>
					<td><input style="width:250px;" type="file" value="{{x.DetailedDescription}}" readonly /></td>			
					<td><input style="width:75px;"  type="text" value="{{x.Price}}" readonly /></td>
					<td><input style="width:25px; height:25px;" type="checkbox" ng-model="chkselct"								 					 
							   								    cam-variable-name="isItemSelected"													
							   								    cam-variable-type="Boolean" /></td>
					<td ng-show="chkselct"><input style="width:30px;" id="quantity" type="number" ng-model="Quantity" value="{{x.Quantity}}"
																	  			   cam-variable-name="quantity" min="1"
																	  			   cam-variable-type="Integer" /></td>
					<td ng-init="$parent.total = $parent.total + (x.Price * x.Quantity)">{{x.Price * x.Quantity}} €</td>
				</tr>
				<tr>
					<td><b>Total</b></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td><b>{{total}} €</b></td>
				</tr>
			</tbody>
		</table>
	</div>
</form> 

In Tasklist, I see this one when I load my form:

For every selected category of my list I want to calculate its cost by multiplying its price by the quantity and also the total cost by adding all of the individual costs.

I took a look in many examples in https://stackoverflow.com/questions/22731145/calculating-sum-of-repeated-elements-in-angularjs-ng-repeat but I am a bit confused.

Can anyone help me please?

Thanks,
Steve


#6

Hi @steftriant,

do you see an error in the console output of the browser (Press F12 -> Console)?
Could you please share your project in Github? Then, it is easier to understand the problem.

Cheers
kristin


#7

Hi @steftriant,

please check whether your values Quantity and Price are numbers. It could be that you get NaN because the both fields are not numbers but text.

Cheers
kristin


#8

Hi @kristin.

Many thanks for your interest.

  1. I can’t understand exactly what you mean. Where must I press F12 to see the console output? I tried it
    in the page of my Tasklist but I saw nothing.
    I just created my first repository in Github with the name “My-first-repo” and I have uploaded there
    the bpmn file with my process diagram and my html forms with the code. If you want from me to do sth
    else you can tell me.

  2. I just corrected the type of my variable “price” in my code (I had firstly defined it as a “text” in order to be
    able to put the sign of “€” but nothing changed with the result (NaN). You can see analytically my code
    in Github if you want.

    Please let me know if you have any possible idea.

    Thanks a lot,
    Steve


#9

Hi @steftriant,

1.) When you are in your browser, you press F12 and then you can use the developer tools. There are different tabs and the console which shows errors, warnings and log statements.
Thank you for sharing your process and user task forms.
The problem could be that the quantity field has no value when you loading the task form. This means, you need to react on the input change of the quantity field.
Now, you show the quantity field only when the check box for that is enabled. But you display directly the total sum of price and quantity and don’t change the total sum after changing the quantity value.

Does it helps?

Cheers
kristin


#10

Hi again @kristin.

Ok, in which browser page have I to check for possible errors in my console output and what can I understand from this? In Tasklist for example?

As for your comments, I have defined as hidden the quantity field because I want to display it only when the user selects the respective item (you can imagine something like a shopping cart).

You mean that I may make the calculation only when the respective item is selected from checkbox? Because, in this case only, the quantity field has a value for making the calculation.

I am going to see also one more similar example which I found here http://jsfiddle.net/slav123/75m7e/3/ and play a bit with the code.

Thank you again,
Steve


#11

Hi @steftriant,

yes you can do it e.g. on the tasklist page. When you have some for example console.log statements in your code, you can see this output in the console of the browser.

Yes, I mean the problem must be the quantity value. If you delete x.Quantity from your calculation, you see the value of x.Price. I think, you can get it working after reworking the select-items.html.

Cheers
kristin


#12

Hi again @kristin and to anyone else.

I 've edited my code, based on this example http://jsfiddle.net/slav123/75m7e/3/ and I managed to make the calculations in my table as you can see in the following screenshot:

But, I 've been facing some issues:

  1. The total sum is displayed only if all the items are selected.

  2. I want to increase or decrease the total sum based on checkbox click (e.x. if I unselect an item, I want to decrease respectively the total sum). So, I want to play with the checkboxes mainly here. Something like this example: https://stackoverflow.com/questions/28622891/how-to-calculate-the-total-amount-when-checkbox-is-cheked-and-item-added-to-cart

For anyone who could help me, I 've just added the updated html file (select-items) in my repository (My-first-repo) on GitHub.

I also uploaded my code here:

<form role="form" name="selectForm">
	<script cam-script type="text/form-script">
		camForm.on('form-loaded', function() {																			// The variable 'item' has not been loaded (fetched) from the server yet.
			camForm.variableManager.fetchVariable('item');																// We tell the "Form SDK" to fetch the 'json' variable named 'item'.
		});
		camForm.on('variables-fetched', function() {																	// The variable 'item' has been loaded (fetched) from the server
			$scope.item = camForm.variableManager.variableValue('item');												// and is bound to the current AngularJS $scope of the form.
		});
		$scope.total = function() {
			var total = 0;
			angular.forEach($scope.item, function(x) {
				total += x.Price * x.Quantity;
			})
		return total;
		}
	</script>
	<h2>My Order List</h2>																							
	<div>
		<table style="width:100%;">
			<thead>
				<tr>
					<th style="width:140px;">Category</th>
					<th style="width:305px;">Brief Description</th>
					<th style="width:250px;">Detailed Description</th>
					<th style="width:75px;" >Price</th>
					<th></th>
					<th>Quantity</th>
					<th>Subtotal</th>
				</tr>			
			</thead>
			<tbody>
				<tr ng-repeat="x in item track by $index">
					<td><input style="width:140px;" type="text" value="{{x.Category}}" readonly /></td>
					<td><input style="width:305px;" type="text" value="{{x.BriefDescription}}" readonly /></td>
					<td><input style="width:250px;" type="file" value="{{x.DetailedDescription}}" readonly /></td>			
					<td><input style="width:75px;"  type="number" value="{{x.Price}}" readonly /></td>
					<td><input style="width:25px;height:25px;" type="checkbox" ng-model="chkselct"								 					 
							   								   cam-variable-name="isItemSelected"													
							   								   cam-variable-type="Boolean" /></td>
					<td ng-show="chkselct"><input style="width:50px;" id="quantity" type="number" ng-model="x.Quantity"
												   					  				cam-variable-name="quantity" min="1"
												   					  				cam-variable-type="Integer" /></td>
					<td>{{x.Price * x.Quantity | currency}}</td>
				</tr>
				<tr>
					<td><b>Total</b></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td><b>{{total() | currency}}</b></td>
				</tr>
			</tbody>
		</table>
	</div>
</form> 

Thank you,
Steve


#13

Hi @steftriant,

I changed your form a bit and now it is working. The problem was that your quantity has only a value when you activate the checkbox and fill the quantity. This means, you get only a correct number for total when all quantity fields are set.
When you want to calculate the total sum regarding the enabled price and quantity fields, you need a bit more logic.

<form role="form" name="selectForm">
  <script cam-script type="text/form-script">
    camForm.on('form-loaded', function() {                                      // The variable 'item' has not been loaded (fetched) from the server yet.
      camForm.variableManager.fetchVariable('item');                                // We tell the "Form SDK" to fetch the 'json' variable named 'item'.
    });
    camForm.on('variables-fetched', function() {                                  // The variable 'item' has been loaded (fetched) from the server
      $scope.item = camForm.variableManager.variableValue('item');                        // and is bound to the current AngularJS $scope of the form.
    });

    $scope.changeQuantity = function(x, index, chkselct) {
      console.log('X: ' + x.Quantity + ', chkselct: ' + chkselct + ', index: ' + index);
      if (!chkselct) {
        x.Quantity = undefined;
      }
      $scope.item[index] = x;
      $scope.total = total();
    }

    function total() {
      var total = 0;
      angular.forEach($scope.item, function(x) {
        if (x.Quantity) {
          total += x.Price * x.Quantity;
        }
      })
      console.log('Total: ' + total);
      return total;
    }

  </script>
  <h2>My Order List</h2>                                              
  <div>
    <table style="width:100%;">
      <thead>
        <tr>
          <th style="width:140px;">Category</th>
          <th style="width:305px;">Brief Description</th>
          <th style="width:250px;">Detailed Description</th>
          <th style="width:75px;" >Price</th>
          <th></th>
          <th>Quantity</th>
          <th>Subtotal</th>
        </tr>     
      </thead>
      <tbody>
        <tr ng-repeat="x in item track by $index">
          <td><input style="width:140px;" type="text" value="{{x.Category}}" readonly /></td>
          <td><input style="width:305px;" type="text" value="{{x.BriefDescription}}" readonly /></td>
          <td><input style="width:250px;" type="file" value="{{x.DetailedDescription}}" readonly /></td>      
          <td><input style="width:75px;"  type="number" value="{{x.Price}}" readonly /></td>
          <td><input style="width:25px;height:25px;" type="checkbox" ng-model="chkselct"                           
                                   cam-variable-name="isItemSelected"                         
                                   cam-variable-type="Boolean" ng-change="changeQuantity(x, $index, chkselct)" /></td>
          <td ng-show="chkselct"><input style="width:50px;" id="quantity" type="number" ng-model="x.Quantity"
                                              cam-variable-name="quantity" min="1"
                                              cam-variable-type="Integer" ng-change="changeQuantity(x, $index, chkselct)" /></td>
          <td>{{x.Price * x.Quantity | currency}}</td>
        </tr>
        <tr>
          <td><b>Total</b></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td></td>
          <td><b>{{total | currency}}</b></td>
        </tr>
      </tbody>
    </table>
  </div>
</form>

Cheers
kristin


#14

Hi again @kristin and to anyone else.

I tested the code and is ok now regarding the calculations. Thank you so much for this. :slightly_smiling_face:

At the moment, I’ve been trying to display (something like adding) each selected item from my existing table to a new one in the same (or in the next task form) in order to have only the selected items displayed for the next user in my process.
I’ve added some things in the HTML section of my code but I don’t know how to handle the script section.
I’ve tried to get some ideas (like creating a 2nd array for the selected items) from this example again (https://stackoverflow.com/questions/28622891/how-to-calculate-the-total-amount-when-checkbox-is-cheked-and-item-added-to-cart) but I find difficult to combine it with your previous modifications in my code. :confused:

My final purpose in this task is to display/add all the selected items and the sums from my existing table to a new one. Have I to create a new json variable here?

I 've uploaded my modified html file (select-items) in my repository (My-first-repo) on GitHub and I also posted here my code in case anyone could help me of course.

<form role="form" name="selectForm">
	<script cam-script type="text/form-script">
		camForm.on('form-loaded', function() {																			// The variable 'item' has not been loaded (fetched) from the server yet.
			camForm.variableManager.fetchVariable('item');																// We tell the "Form SDK" to fetch the 'json' variable named 'item'.
		});
		camForm.on('variables-fetched', function() {																	// The variable 'item' has been loaded (fetched) from the server
			$scope.item = camForm.variableManager.variableValue('item');												// and is bound to the current AngularJS $scope of the form.
		});
		$scope.selectedItem = [];
		$scope.changeQuantity = function (x,index,chkselct) {															// We make a function named "changeQuantity".
			console.log('x: ' +x.Quantity+ ', chkselct: ' +chkselct+ ', index: '+ index);
			if (!chkselct) {																							// If item's checkbox is not "enabled",
				x.Quantity=undefined;																					// then the respective "quantity" field has not a value.
			}
			$scope.item[index] = x;																						// We find the "selected" item (using "index") from the Array.  
			$scope.total = total();																						// We make a function named "total".
		}
		function total() {																								// When "total" function gets called,
			var total = 0;																								// the variable "total" is initialized.
			angular.forEach($scope.item, function(x) {																	// The "forEach" function reads each selected "item" using "index" (assigned to "x") of the array.
				if (x.Quantity) { 																						// If item's checkbox is "enabled" and "quantity" field has a value,
					total += x.Price * x.Quantity;																		// then we can calculate "total" by calling the "total" function.												
				}
			})
			console.log('Total: ' + total);																				// "total" value is displayed.
			return total;																								// "return" statement stops the execution of the "total" function and returns a value from that function.
		}
	</script>
	<div><h2>My List of Selected Items</h2></div>
	<div>
		<table ng-show="selectedItem.length>0" style="width:100%;">
			<thead>
				<tr>
					<th style="width:140px;">Category</th>
					<th style="width:305px;">Brief Description</th>
					<th style="width:250px;">Detailed Description</th>
					<th style="width:75px;">Price</th>
					<th style="width:50px;">Quantity</th>
					<th style="width:100px;">Subtotal</th>
				</tr>
			</thead>
			<tbody>
				<tr ng-repeat="y in selectedItem track by $index">
					<td><input style="width:140px;" type="text" value="{{y.Category}}" readonly /></td>
					<td><input style="width:305px;" type="text" value="{{y.BriefDescription}}" readonly /></td>
					<td><input style="width:250px;" type="file" value="{{y.DetailedDescription}}" readonly /></td>
					<td><input style="width:75px;"  type="number" value="{{y.Price}}" readonly /></td>
					<td><input style="width:50px;"  type="number" value="{{y.Quantity}}" readonly /></td>
					<td><input style="width:100px;" type="number" value="{{y.Price * y.Quantity | currency}}"/></td>
				</tr>
				<tr>
					<td><b>Total</b></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td><b>{{total | currency}}</b></td>	
				</tr>
			</tbody>
		</table>
	</div>
	<div ng-show="selectedItem.length<=0"><h3>No item selected</h3></div>
	<hr>
	<h2>My Order List</h2>																							
	<div>
		<table style="width:100%;">
			<thead>
				<tr>
					<th style="width:140px;">Category</th>
					<th style="width:305px;">Brief Description</th>
					<th style="width:250px;">Detailed Description</th>
					<th style="width:75px;" >Price</th>
					<th></th>
					<th>Quantity</th>
					<th>Subtotal</th>
				</tr>			
			</thead>
			<tbody>
				<tr ng-repeat="x in item track by $index">
					<td><input style="width:140px;" type="text" value="{{x.Category}}" readonly /></td>
					<td><input style="width:305px;" type="text" value="{{x.BriefDescription}}" readonly /></td>
					<td><input style="width:250px;" type="file" value="{{x.DetailedDescription}}" readonly /></td>			
					<td><input style="width:75px;"  type="number" value="{{x.Price}}" readonly /></td>
					<td><input style="width:25px;height:25px;" type="checkbox" ng-model="chkselct"													 					 
							   								   cam-variable-name="isItemSelected"													
							   								   cam-variable-type="Boolean"
							   								   ng-change="changeQuantity(x, $index, chkselct)" /></td>										<!-- The "ng-change" directive calls the "changeQuantity" function when the value of checkbox changes. -->										
					<td ng-show="chkselct"><input style="width:50px;" id="quantity" type="number" ng-model="x.Quantity"					
												   					  				cam-variable-name="quantity" min="1"
												   					  				cam-variable-type="Integer" 
												   					  				ng-change="changeQuantity(x, $index, chkselct)" /></td>					<!-- The "ng-show" directive shows the "quantity" input field when a checkbox is checked. -->					
					<td>{{x.Price * x.Quantity | currency}}</td>																								<!-- The "subtotal" amount (for each selected item) is displayed. -->
				</tr>
				<tr>
					<td><b>Total</b></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td></td>
					<td><b>{{total | currency}}</b></td>																										<!-- The "total" amount is displayed. -->
				</tr>
			</tbody>
		</table>
	</div>
</form> 

Thanks,
Steve


#15

Hi @steftriant,

what should happen with the selected items? Should it only displayed or there are changes possible?

If you want display the selected items, you could do it in the same user task.
If you want to allow changes, you could do it in a new user task form.

Could you did some progress to get it working?

Cheers
kristin


#16

Hi @kristin and to anyone else.

My final purpose on this task (Select items) is to create a list ( 2nd html table) with all the selected items, their sums and the total sum of course in order to make an automatic comparison afterwards. If you take a look in the following screenshot of my process diagram you will notice that the selected items are going to be gathered by the 1st user of my bpm scenario.

So, I suppose that I must create a 2nd array in this task form (selectedItems) in order to separate the selected from the unselected items (like this example: http://jsfiddle.net/zqpxtbzo/). But I’m not sure if I have to create a 2nd json variable (like in my 1st task form). I tell you that because I want to transfer (fetch) the list of selected items in the next task of my process (Gather the total needs) only if the automatic comparison (which is going to be done in the script task) evaluates to true.

I’m going to make an effort today to write the proper code because I was very busy all the week and I will let you know of course for any possible results.
Thank you so much and have fun! :slightly_smiling_face:

Cheers,
Steve