1

I want to calculate the total on enter press in jqgrid. Tried to capture the enter key event of the jqgrid when the user presses enter to save the editing row but not able to do so.

Here is code snippet of my jqgrid (MarksTbl) columns

 colModel: [
              { name: 'Id', index: 'Id', hidden: true },
              { name: 'Maths', index: 'Maths', hidden: true },
              { name: 'Eng', index: 'Eng', editable: true },
              { name: 'Sci', index: 'Sci', editable: true },
              { name: 'TotalMarks', index: 'TotalMarks'}
           ]

To invoke row editing i am calling the 'editRow' on 'onSelectRow'. The requirment is i want to calculate the total(ie. Maths+Eng+Sci whatever the users input is) and set the result of it in 'TotalMarks' sell of saved row

I have tried using the key=true, even tried to bind the 'OnEnter' event to the grid mentioned over here.

Not knowing how can achieve this feature(just calculate the total on press enter to save record set the corresponding value in total cell).. It would be great help if @Oleg you can guide me on these.

Community
  • 1
  • 1
Rekha
  • 45
  • 2
  • 8
  • see if these events help you http://www.trirand.com/jqgridwiki/doku.php?id=wiki:inline_editing#editrow – G.Mendes Jul 23 '14 at 10:45
  • 1
    What you do exactly? Where is "the total"? Is it one column of the grid? Is it the value in the footer of the grid?... `editRow` support `keys` option which you can set to true, but you should post **how you use inline editing** (do you call `editRow` directly in `onSelectRow` for example? do you use `inlineNav`? do you use `formatter: "actions"`?). The correct text don't provide any details of your implementation and it describes neither clear enough what you do nor what you want to do. Sorry. – Oleg Jul 23 '14 at 11:13
  • @Oleg thanks for your reply... And i am really sorry that i did made it clear at first time.. I have update the question as per your need can please go through it and help with that.. And it will also help if you can tell me how i can get the grade total too dynamically.. Is it possible of cell change event or something similar to it. – Rekha Jul 24 '14 at 05:16

1 Answers1

4

Working with grids where there is column, which depends from another one, is common situation. So I try to make detailed answer on your question.

First of all you can implement your requirement in the following simple way: you can use aftersavefunc option of editRow to make some custom actions after the row have been modified. For example you can recalculate new value for "TotalMarks" column and explicitly call setRowData with {TotalMarks: newValue} as parameter.

On the other side it's good in general to use custom formatter on "TotalMarks" column to make "virtual" column which value is not in the source data, but which value will be just calculated based on the value of other columns. In the case you need just define the corresponding custom formatter and, if you use local datatype, define custom sorttype (see the answer, this one and this one). If you use editing of data then you should don't forget to define unformat (unformatter function).

The following demo demonstrates the approach. It have "total" column which content calculated as the sum of content of "amount" and "tax" columns. The input data don't contains any value for "total" column. The column "total" is editable, but because of editoptions: { disabled: "disabled" } option the user can't change the value directly:

enter image description here

The corresponding definition of the "total" is

{ name: "total", width: 60, template: numberTemplate,
    sorttype: function (cellValue, rowObject) {
        return parseFloat(rowObject.amount) + parseFloat(rowObject.tax);
    },
    formatter: function (cellValue, options, rowObject) {
        var total = parseFloat(rowObject.amount) + parseFloat(rowObject.tax);
        return $.fn.fmatter.call(this, "currency", total, options);
    },
    unformat: function (cellValue, options, cell) {
        // make copy of options
        var opt = $.extend(true, {}, options);

        // change opt.colModel to corresponds formatter: "currency"
        opt.colModel.formatter = "currency";
        delete opt.colModel.unformat;

        // unformat corresponds to formatter "currency"
        return $.unformat.call(this, cell, opt);
    },
    editoptions: { disabled: "disabled" } }

By the way, I used the following code of onSelectRow to implement inline editing:

onSelectRow: function (rowid) {
    var $self = $(this),
        // savedRows array is not empty if some row is in inline editing mode
        savedRows = $self.jqGrid("getGridParam", "savedRow");
    if (savedRows.length > 0) {
        $self.jqGrid("restoreRow", savedRows[0].id);
    }
    $self.jqGrid("editRow", rowid, { keys: true });
}

How one can see the code don't use any lastSel variable like in the well known code example. It could be practical in case of usage multiple editable grids on one HTML page.

If one don't want to make the column "total" editable at all one can use aftersavefunc to force recalculation of the total:

onSelectRow: function (rowid) {
    var $self = $(this),
        // savedRows array is not empty if some row is in inline editing mode
        savedRows = $self.jqGrid("getGridParam", "savedRow");
    if (savedRows.length > 0) {
        // cancel editing of the previous selected row if it was in editing state.
        // jqGrid hold intern savedRow array inside of jqGrid object,
        // so it is safe to call restoreRow method with any id parameter
        // if jqGrid not in editing state
        $self.jqGrid("restoreRow", savedRows[0].id);
    }
    $self.jqGrid("editRow", rowid, {
        keys: true,
        aftersavefunc: function (rowid) {
            var $this = $(this),
                rowObject = $this.jqGrid("getGridParam", "datatype") === "local" ?
                    $this.jqGrid("getLocalRow", rowid) :
                    {
                        amount: $this.jqGrid("getCell", rowid, "amount"),
                        tax: $this.jqGrid("getCell", rowid, "tax")
                    };
            // one ca call setRowData below with two properties
            // only which are required for
            $this.jqGrid("setRowData", rowid, {
                amount: rowObject.amount,
                tax: rowObject.tax,
                total: "dummy"
            });
        }
    });
}

The column "total" has editable: false property instead of editoptions: { disabled: "disabled" } and the editing looks more comfortable

enter image description here

Community
  • 1
  • 1
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Thanks for your quick reply... I really thankful for your help Will try this and update you if it fix my problem.. – Rekha Jul 25 '14 at 05:49
  • Thanks a lot @Oleg it worked for me... It cleared most of my doubts too.. :) – Rekha Jul 28 '14 at 10:38
  • One answer i was looking for is... Is there any way to validate the total column in this scenario... As i want to make sure that the total must be greater than certain level...Before any particular record gets saved. @Oleg sorry for bothering you for this. – Rekha Jul 28 '14 at 11:02
  • 1
    @Rekha: If you need just set **fixed** limit to `total` then you can use `minValue` or `maxValue` of `editrules` or to use `custom: true` and [custom_func](http://www.trirand.com/jqgridwiki/doku.php?id=wiki:common_rules#custom_checking_example). You can additionally monitor `change` event (using `dataEvents` in `editoptions`) in `total` column and mark the input with `ui-state-error` class (like [here](http://stackoverflow.com/a/6162086/315935)) **during** the user change it. It will be difficult if you need to validate **multiple** fields (dependent fields), but even this is possible. – Oleg Jul 28 '14 at 11:34
  • Actually the 'total' field which i am talking about is an non-editable field its value is set based on the calculation of the other fields.. Due to that i am facing difficulty in validation on it... As i am not able to set the custom validation by setting the `editrule` property. So how can i achieve the same by keeping the total column as non-editable as the above example describes. – Rekha Jul 28 '14 at 12:02
  • @Rekha: Probably you can use custom validation of some other *editable* field (`Sci`, `Eng`, `Maths`) which large value can break the limit on the total. You can compare the current value with the *previous* value (you can examine `savedRow` parameter of jqGrid, which is array of items, where jqGrid saves values from editing rows *before* starting editing). In the vay you can detect which fields are edited by the user, you can mark red the fields and display an message about the limit on `total`. In any way I think that you can get pretty good error description for the user. – Oleg Jul 28 '14 at 12:48
  • I have one more requirement i want to merge the footer row to show the grand total I have referred you answer over [here](http://stackoverflow.com/questions/7029511/is-there-a-way-to-add-a-summary-row-to-jqgrid-treeview)... But i was not able to get it(And could not comment over there as hv less reputation)... Can you please guide me how can i achieve that I want to do something like this in footer row Total: 54 How is it possible? – Rekha Jul 29 '14 at 10:19
  • @Rekha: The main advantage of stackoverflow is to *share* the questions and the answers with other. It seems you have new question. So you should better *open new question* where you describe the problem and your current attempts. Additionally it's important in the most cases whether you work with *local* data or with remote data (`datatype` is `"json"` or `"xml"` without `loadonce: true`). In case of remote data you can calculate the grand total *on the server* and just return the result. In case of *local* data the calculation have to be done locally. – Oleg Jul 29 '14 at 10:25
  • Thanks... @Oleg i will sure post my problem i am facing as the diffrent question. – Rekha Jul 29 '14 at 10:57
  • Not using `lastSel` approach is what I was looking for ! – Alireza Fattahi Oct 28 '16 at 08:56
  • @AlirezaFattahi: If you don't like `lastSel` approach and want to write clean code without it then I'd recommend you to look to [the answer](http://stackoverflow.com/a/34976517/315935), which use both `beforeSelectRow` and `onSelectRow`. The problem could be if one need **to save** the data with respect of `saveRow` instead of discarding the changes by call of `restoreRow`. The problem could be any kind of error (like validation errors) in `saveRow`. To stay on the unsaved row one should call `saveRow` in `beforeSelectRow`. In case of saving to server one can select the row in `aftersavefunc`. – Oleg Oct 28 '16 at 10:54