Questions and discussion about using ProcessMaker: user interface, running cases & functionality

Moderator: amosbatto

By cosyxu
#796067
Good morning,

I was wondering is there any way to improve the performance of JS code in Dyanform when I had more than 200 rows in my grid?

I am using web-entry form, when I click my "search button", it runs an ajax function to manipulate data from DB to the Grid, when the number of rows excess 200, it become very slow to show the full grid.

Any ideas?

Thanks,
Yuan
By amosbatto
#796069
Short answer: No. The JS code in DynaForms is already minimized, so I don't think you can do much more to speed it up.

You can modify your AJAX to only return only 50 rows at a time and display buttons to show the second, third, fourth, etc. pages of the results.
Get the number of pages: SELECT COUNT(*) FROM X
Then display the buttons:
Page 1: SELECT * FROM X LIMIT 50
Page 2: SELECT * FROM X LIMIT 51, 100
Page 3: SELECT * FROM X LIMIT 101, 150
Page 4: SELECT * FROM X LIMIT 151, 200
etc.

Each time the user clicks on a button, do the query of your database. Use JavaScript to clear all the rows in the grid with grid.deleteRow() and then use grid.addRow() to add each row returned by AJAX to the grid.
By cosyxu
#796075
Hi Amosbatto,

Thank you for your reply.

I was wondering is there any way to restructure the following code?
Code: Select all
myJSON = JSON.parse(xmlhttp.responseText);
for (var i = 0; i < oLength; i++) {  
newRow = [ 
		    {"value": myJSON[i].category},
		    {"value": myJSON[i].item},
		    {"value": myJSON[i].price},
		    {"value": 0}
		 ];
$("#grid_order").addRow(newRow
});
When I use the above code, it takes 47s to update a grid with 200 rows; and it takes 4s to update a grid with 37 rows.

Therefore, is there any way to change the code and improve the speed of performance?

Many thanks,
Yuan
By amosbatto
#796085
I don't know how to speed up grid.addRow(). You should file a bug report asking for a function to set all the rows in a grid at once.

If this were not a web entry, you could use REST to set the case variable associated with the grid and then call location.reload(). Unfortunately, you are using web entry, so the case doesn't yet exist and you can't set the grid's case variable.
By amosbatto
#796086
If you want to check the code for grid.addRow(), you can find it at line 6786 in workflow/public_html/lib/pmdynaform/build/js/PMDynaform.js

If you only want to read the contents of your grid and not edit it, then I recommend using DataTables in a Panel which is much faster:
http://wiki.processmaker.com/3.0/Panel_ ... e_DynaForm

If you want editing of the table, then see:
https://editor.datatables.net/
You will need to add JS code to your form that is executed by form.setOnSubmit(). Your code can convert the contents of the DataTable to a JSON string and save it in a hidden field. Then a later trigger in your process can call json_decode(@@myHidden) and save it as a normal grid.
By cosyxu
#796124
Hi amosbatto,

Thank you for your reply and the resource.

I still prefer to use grid because I also need the calculation function of the grid. And I have found out it is the form.setOnChange() that slow down the grid.

Therefore, if I don't use JavaScript to calculate the grid(I know it is advised to use js), I can use processmaker built-in function(sum), however I was wondering is there any way that I can change the content of sum area? For example: Your Total is : XXX.

[img]
2017-11-14_9-02-19.png
2017-11-14_9-02-19.png (60.38 KiB) Viewed 1058 times
[/img]
Please see attached screen shot.

Many thanks,
Yuan
By amosbatto
#796125
You can set the value of a summed column with this code:
$("#sum-GRID_ID-FIELD_ID").val("X")
Example:
$("#sum-accountsGrid-price").val("353.50")

But it will be overwritten each time a value in the column is changed. You can hide the field and create another field that you will set with JavaScript. For example:
Code: Select all
$("#sum-accountsGrid-price").hide();
$("#sum-accountsGrid-price").parent().append(
'<input id="sum-accountsGrid-price2" style="width: 50%;" readonly="readonly" data-original-title="" title="">');
$("#sum-accountsGrid-price2").val("353.60");
By cosyxu
#796129
Hi Amosbatto,


Thank you for your solution.

Could I also ask how to add a "loading" image before the grid has been fully display?

Just like when you submit a web-form, there is a "loading image" displaying until the form has been submitted.
2017-11-14_14-10-37.png
2017-11-14_14-10-37.png (4.62 KiB) Viewed 1045 times
Thanks in advance,
Yuan
User avatar
By programerboy
#796140
Hi Amosbatto,

Thanks for your answers. But I think Processmaker must add a solution for create paging in grids with ajax, In addition to the method with JavaScript that exist now, Because it crash when the number of records increases and designer must use panel and external libraries and etc.

Thanks
By amosbatto
#796146
cosyxu wrote:Could I also ask how to add a "loading" image before the grid has been fully display?

Just like when you submit a web-form, there is a "loading image" displaying until the form has been submitted.
2017-11-14_14-10-37.png
Yuan,
To display the loading spinning circles in your DynaForm, you can use this code:
$("body").append("<div class='pmDynaformLoading'></div>");

And to remove them, you can use this code:
$("body").find("div.pmDynaformLoading").remove();
By amosbatto
#796147
programerboy wrote:Hi Amosbatto,

Thanks for your answers. But I think Processmaker must add a solution for create paging in grids with ajax, In addition to the method with JavaScript that exist now, Because it crash when the number of records increases and designer must use panel and external libraries and etc.

Thanks
Programerboy, please file a bug report requesting this new feature at http://bugs.processmaker.com, and post a link to your bug report here.
By cosyxu
#796153
Hi Amosbatto,


Thank you very much for your solution.

In addition to that, it seems Dynaform use "bootstrap 3 datetimepicker" from
http://eonasdan.github.io/bootstrap-dat ... field-only.

If I'd like to use other pattern or style of the datetimepicker control, where and how should I do?

For example, if I want to use " No Icon (input field only)" style, how should I change the existing datetime control to this style?


Thanks,
Yuan
By amosbatto
#796157
If you want to get rid of the calendar icon, then you can do this:
$("#DATETIME-ID").find("span.input-group-addon").hide()
By cosyxu
#796158
amosbatto wrote:If you want to get rid of the calendar icon, then you can do this:
$("#DATETIME-ID").find("span.input-group-addon").hide()

If I hide the span, then I can't select the date when I click it.

I have also trid this code, it works, but when I click the text field to select a date, it still show the "required field" error because the value didn't pass into the hiden field for datetime control.
Code: Select all
$("#functionDate").find("input").datetimepicker();


Any ideas? Thanks.
2017-11-15_15-52-18.png
2017-11-15_15-52-18.png (6.95 KiB) Viewed 1020 times
2017-11-15_15-53-11.png
2017-11-15_15-53-11.png (39.54 KiB) Viewed 1020 times
Yuan
By amosbatto
#796168
Yuan,
You can use this JS code:
Code: Select all
$("#dueDate").find("span.input-group-addon").hide(); 
$("#dueDate").find("input").datetimepicker();

$("#form\\[dueDate\\]").blur(function() {
  var dt = moment(this.value).format('YYYY-MM-DD HH:mm:ss');
  $("#form\\[dueDate_label\\]").val(dt);
});
Where "dueDate" is the ID of the datetime field.
By cosyxu
#796169
hi Amosbatto,

Thank you for your code.

I have tried and it pass to the value to the <input> but it still show "required error".

Could I also ask how to implement the linked pickers? Please see attached code:
Code: Select all
       $('#startDate').datetimepicker();
         $('#endDate').datetimepicker({
            useCurrent: false 
        });
        $("#startDate").on("dp.change", function (e) {
            $('#endDate').data("DateTimePicker").minDate(e.date);
        });
        $("#endDate").on("dp.change", function (e) {
            $('#startDate').data("DateTimePicker").maxDate(e.date);
        });
Any ideas?
Reference:https://eonasdan.github.io/bootstrap-da ... ed-pickers
2017-11-16_12-13-36.png
2017-11-16_12-13-36.png (11.6 KiB) Viewed 1001 times
Thanks,
Yuan
By amosbatto
#796186
cosyxu wrote:I have tried and it pass to the value to the <input> but it still show "required error".
Don't make it "required" and add code to the form.setOnSubmit() event handler to check whether it is empty.
cosyxu wrote:Could I also ask how to implement the linked pickers? Please see attached code:
Code: Select all
       $('#startDate').datetimepicker();
         $('#endDate').datetimepicker({
            useCurrent: false
        });
        $("#startDate").on("dp.change", function (e) {
            $('#endDate').data("DateTimePicker").minDate(e.date);
        });
        $("#endDate").on("dp.change", function (e) {
            $('#startDate').data("DateTimePicker").maxDate(e.date);
        });
Any ideas?
I can't figure out how to change the properties of existing datetime fields. The workaround is to hide two existing date fields and then place to new date fields in a Panel to replace them. Here is the Panel's HTML code:
Code: Select all
    <div class='col-md-5'>
        <div class="form-group">
            <b>Start Date: </b>
            <div class='input-group date' id='startDate2'>
              <input type='text' class="form-control" />
              <span class="input-group-addon">
                    <span class="glyphicon glyphicon-calendar"></span>
              </span>
            </div>
        </div>
    </div>
    <div class='col-md-5'>
        <div class="form-group">
            <b>End Date: </b>
            <div class='input-group date' id='endDate2'>
              <input type='text' class="form-control" />
              <span class="input-group-addon">
                    <span class="glyphicon glyphicon-calendar"></span>
              </span>
            </div>
        </div>
    </div>
Then, call datetimepicker() on those two new fields in the JS code:
Code: Select all
$('#startDate').hide();
$('#endDate').hide();
$('#datesPanel').css('overflow', 'visible');
$("div.pmdynaform-container").css("overflow", "visible");
$("form.pmdynaform-form").css("overflow", "visible");

$('#startDate2').datetimepicker({
  format: "YYYY-MM-DD" 
});

$('#endDate2').datetimepicker({
  useCurrent: false,
  format: "YYYY-MM-DD"
});

$("#startDate2").on("dp.change", function (e) {
  var newDate = moment(e.date).format("YYYY-MM-DD HH:mm:ss");
  $("#endDate2").data("DateTimePicker").minDate(newDate);
  $("#startDate").setValue(newDate);
});

$("#endDate2").on("dp.change", function (e) {
  var newDate = moment(e.date).format("YYYY-MM-DD HH:mm:ss");
  $('#startDate2').data("DateTimePicker").maxDate(newDate);
  $("#endDate").setValue(newDate);
});
LinkedDateTimeFields.png
LinkedDateTimeFields.png (91.32 KiB) Viewed 980 times
See the attached process that shows how to implement it:
(27.25 KiB) Downloaded 14 times
By cosyxu
#796189
amosbatto wrote:
cosyxu wrote:I have tried and it pass to the value to the <input> but it still show "required error".
Don't make it "required" and add code to the form.setOnSubmit() event handler to check whether it is empty.
cosyxu wrote:Could I also ask how to implement the linked pickers? Please see attached code:
Code: Select all
       $('#startDate').datetimepicker();
         $('#endDate').datetimepicker({
            useCurrent: false
        });
        $("#startDate").on("dp.change", function (e) {
            $('#endDate').data("DateTimePicker").minDate(e.date);
        });
        $("#endDate").on("dp.change", function (e) {
            $('#startDate').data("DateTimePicker").maxDate(e.date);
        });
Any ideas?
I can't figure out how to change the properties of existing datetime fields. The workaround is to hide two existing date fields and then place to new date fields in a Panel to replace them. Here is the Panel's HTML code:
Code: Select all
    <div class='col-md-5'>
        <div class="form-group">
            <b>Start Date: </b>
            <div class='input-group date' id='startDate2'>
              <input type='text' class="form-control" />
              <span class="input-group-addon">
                    <span class="glyphicon glyphicon-calendar"></span>
              </span>
            </div>
        </div>
    </div>
    <div class='col-md-5'>
        <div class="form-group">
            <b>End Date: </b>
            <div class='input-group date' id='endDate2'>
              <input type='text' class="form-control" />
              <span class="input-group-addon">
                    <span class="glyphicon glyphicon-calendar"></span>
              </span>
            </div>
        </div>
    </div>
Then, call datetimepicker() on those two new fields in the JS code:
Code: Select all
$('#startDate').hide();
$('#endDate').hide();
$('#datesPanel').css('overflow', 'visible');
$("div.pmdynaform-container").css("overflow", "visible");
$("form.pmdynaform-form").css("overflow", "visible");

$('#startDate2').datetimepicker({
  format: "YYYY-MM-DD" 
});

$('#endDate2').datetimepicker({
  useCurrent: false,
  format: "YYYY-MM-DD"
});

$("#startDate2").on("dp.change", function (e) {
  var newDate = moment(e.date).format("YYYY-MM-DD HH:mm:ss");
  $("#endDate2").data("DateTimePicker").minDate(newDate);
  $("#startDate").setValue(newDate);
});

$("#endDate2").on("dp.change", function (e) {
  var newDate = moment(e.date).format("YYYY-MM-DD HH:mm:ss");
  $('#startDate2').data("DateTimePicker").maxDate(newDate);
  $("#endDate").setValue(newDate);
});
LinkedDateTimeFields.png
See the attached process that shows how to implement it:
linked_date_fields-1.pmx
Thank you very much for the solution!

It works fine.

Thanks,
Yuan
By cosyxu
#798775
Good morning,

I would like to add jQuery Datepicker by using the following method, but I don't know how to add validation for "required field", any ideas?

Code: Select all
var datepairExample ='<div class="input-daterange input-group" id="datepairExample" style="width:98%">'
                          +'<div class="row">'
                              +'<div>'
                              +    '<div class="form-group col-sm-2 col-md-2 col-lg-2 tpl-empty"></div>'
                              +'</div>'                                         
 
                              //add validation
                              +'<div class="has-feedback">'
                                  +'<div id="d1" class="pmdynaform-field-text pmdynaform-edit-text form-group col-sm-4 col-md-4 col-lg-4 pmdynaform-field">'
                                    +'<label for="form[d1]" class="control-label pmdynaform-label col-sm-12 col-md-12 col-lg-12" style="padding-bottom: 5px; text-align: left;">'
                                        +'<span data-toggle="tooltip" data-placement="bottom" title="" class="textlabel">Start Date</span>'
                                        +'<span class="pmdynaform-field-required">*</span>'                             
                                    +'</label>'

                                    +'<div class="datetime-container">' //add class
                                      +'<div class="pmdynaform-field-control col-sm-12 col-md-12 col-lg-12" style="display:inline-table;padding-left:0px">'
                                          +'<input id="form[d1]" name="form[d1]" type="text" style="text-align: left;" class="date start input-md pmdynaform-control-text form-control" placeholder="For example: 15/09/2017" value="" autocomplete="off">'
                                          +'<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>'
                                          +'<input type="hidden" id="form[d1_label]" name="form[d1_label]" value="">'
                                      +'</div>'
                             
                                    +'</div>'  
                                  +'</div>'                                
                              +'</div>'

                              +'<div id="d2" class="pmdynaform-field-text pmdynaform-edit-text form-group col-sm-4 col-md-4 col-lg-4 pmdynaform-field">'
                                +'<label for="form[d2]" class="control-label pmdynaform-label col-sm-12 col-md-12 col-lg-12" style="padding-bottom: 5px; text-align: left;">'
                                    +'<span data-toggle="tooltip" data-placement="bottom" title="" class="textlabel">End Date</span>'
                                    +'<span class="pmdynaform-field-required">*</span>'                             
                                +'</label>'

                                +'<div class="datetime-container">' //add class
                                  +'<div class="pmdynaform-field-control col-sm-12 col-md-12 col-lg-12" style="display:inline-table;padding-left:0px">'
                                      +'<input id="form[d2]" name="form[d2]" type="text"  style="text-align: left;" class="date end input-md pmdynaform-control-text form-control" placeholder="For example: 15/09/2017" value="" autocomplete="off">'
                                      +'<span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>'
                                      +'<input type="hidden" id="form[d2_label]" name="form[d2_label]" value="">'
                                  +'</div>'
                                +'</div>' 
                              +'</div>' 
                             
                               +'<div>'
                              +    '<div class="form-group col-sm-2 col-md-2 col-lg-2 tpl-empty"></div>'
                              +'</div>'                
                          +'</div>'                 
                    +'</div>';

$("#datepairExample").replaceWith(datepairExample);
I also tried to add $("#id").enableValidation(); but it doesn't work.


Thanks,
Yuan
By amosbatto
#798783
$("#id").enableValidation() will only work on a field which has its "required" property marked in the original properties of the control.

I don't recommend replacing the existing field like you are doing, because your data might not be saved correctly when the form is submitted. Add code to the form.setOnSubmit() event handler to check whether the datetime fields are empty. If so, then display an error message with alert() if empty and return FALSE to stop the submit action.
By cosyxu
#798789
amosbatto wrote:$("#id").enableValidation() will only work on a field which has its "required" property marked in the original properties of the control.

I don't recommend replacing the existing field like you are doing, because your data might not be saved correctly when the form is submitted. Add code to the form.setOnSubmit() event handler to check whether the datetime fields are empty. If so, then display an error message with alert() if empty and return FALSE to stop the submit action.

Thank you for your reply.

I have add validation code into the form.setOnChange(), but it seems I can't get the value of the control..... :?:

should I get value like this
Code: Select all
hidden_d1 = $("#form\\[hidden_d1_label\\]").val();
?


Thanks,
Yuan
By amosbatto
#798829
$("#form\\[hidden_d1_label\\]").val() should work. If you post your .json file for the DynaForm, I will look at it.
By cosyxu
#812392
Good morning Amosbatto,


Regarding "Linked Datetime Pickers" problem, I have found a solution for it after testing for a while.

We can use "Textbox" as "Start time" and "End time", also add the following js code to complete a linked datetime:
Code: Select all
$(function () { // using this function with "today validation"

         $("#Start Date").getControl().datetimepicker({
             format: 'dddd, DD MMM YYYY',
             showClear: true,
             showTodayButton: true,
         });

        $("#End Date").getControl().datetimepicker({
             format: 'dddd, DD MMM YYYY',
             useCurrent: false, //Important! See issue #1075
             showClear: true,
             showTodayButton: true,

         });

        $("#Start Date").getControl().on("dp.change", function (e) {
            $('#End Date').getControl().data("DateTimePicker").minDate(e.date);
        });
        $("#End Date").getControl().on("dp.change", function (e) {
            $('#Start Date').getControl().data("DateTimePicker").maxDate(e.date);
        });
  });

Referenced from:
http://eonasdan.github.io/bootstrap-datetimepicker/ [^]

Hope it can help someone who want to add a "Linked Datetime" function.

Regards,
Yuan

I am also interested in a solution to this problem[…]

Hi, I have the problem that I want to have a Dyna[…]

I found a better solution, which I documented here[…]

Session Expiration Issue

Yuan, You can change this message by going to A[…]