How to pass data to url from jqgrid row if hyperlink is clicked
Asked Answered
J

1

3

jqGrid contains quantity column and add to cart button using colmodel below. Inline editing is used to fill quantity. If quantity is fileld and add to cart link on other column is clicked, entered quanty is not passed to AddToCart controller. Product id from id field in json data is passed correctly.

How to pass selected quantity to AddToCart controller (using invoked url query string or something other) ?

colmodel is:

{"label":"AddToCart",
 "name":"Addtocrt_addtocrt",
 "formatter":"showlink",
 "formatoptions": {"baseLinkUrl":"http://MySite.com/Store/AddToCart"}
 },

{"label":"Quantity",
  "name":"Stocks_valkogus",
  "editoptions":{"maxlength":10 }
  "editable":true
   }

Update

Data from server is in json format and row editing mode is used. rowData.Stocks_valkogus returns undefined.

I tried code below. alert box shows that quantityVal is undefined. How to retrieve entered quantity?

{"name":"Addtocrt_addtocrt",
 "formatter":"dynamicLink",
 "formatoptions":{"onClick":addToCartOnClick
}}

function addToCartOnClick(rowId, iRow, iCol, cellValue, e) {
    var iCol = getColumnIndexByName($grid, 'Stocks_valkogus') ,
       quantityVal = $('#' + $.jgrid.jqID(rowId) + '>td:nth-child(' + (iCol + 1) + '>input').val();
    alert(iCol); // returns 3 
    alert(quantityVal); // returns undefined. 
    window.location = 'Store/Details?' + $.param({
        id: rowId,
        quantity: quantityVal
    });
}
Japeth answered 27/1, 2012 at 18:15 Comment(0)
M
4

I understand the problem very good. I agree that both predefined formatter which one can use currently ('showlink' and 'link' formatters) are not flexible enough.

I can suggest you another formatter which you could download here. The usage of the formatter is very easy:

{label: "AddToCart", name: "Addtocrt_addtocrt", formatter: "dynamicLink",
    formatoptions: {
        url: function (cellValue, rowId, rowData) {
            return '/Store/AddToCart' + rowId + '?' +
                $.param({
                    quantity: rowData.Stocks_valkogus
                });
        }
    }
}

The url defined as function will be used in the <a> as the value of href attribute.

Additionally to the url formatoptions the 'dynamicLink' formatter supports target option (with the same meaning as by 'showlink'), cellValue which can be also function and onClick callback with rowId, iRow, iCol, cellValue, e as parameters. If the onClick callback is defined the value of url will be ignored. So one can skip the definition of the formatter option url.

The demo demonstrate the usage of the 'dynamicLink' formatter:

enter image description here

The current code of the formatter: 'dynamicLink' you can find below:

/*global jQuery */
(function ($) {
    'use strict';
    /*jslint unparam: true */
    $.extend($.fn.fmatter, {
        dynamicLink: function (cellValue, options, rowData) {
            // href, target, rel, title, onclick
            // other attributes like media, hreflang, type are not supported currently
            var op = {url: '#'};

            if (typeof options.colModel.formatoptions !== 'undefined') {
                op = $.extend({}, op, options.colModel.formatoptions);
            }
            if ($.isFunction(op.target)) {
                op.target = op.target.call(this, cellValue, options.rowId, rowData, options);
            }
            if ($.isFunction(op.url)) {
                op.url = op.url.call(this, cellValue, options.rowId, rowData, options);
            }
            if ($.isFunction(op.cellValue)) {
                cellValue = op.cellValue.call(this, cellValue, options.rowId, rowData, options);
            }
            if ($.fmatter.isString(cellValue) || $.fmatter.isNumber(cellValue)) {
                return '<a' +
                    (op.target ? ' target=' + op.target : '') +
                    (op.onClick ? ' onclick="return $.fn.fmatter.dynamicLink.onClick.call(this, arguments[0]);"' : '') +
                    ' href="' + op.url + '">' +
                    (cellValue || '&nbsp;') + '</a>';
            } else {
                return '&nbsp;';
            }
        }
    });
    $.extend($.fn.fmatter.dynamicLink, {
        unformat: function (cellValue, options, elem) {
            var text = $(elem).text();
            return text === '&nbsp;' ? '' : text;
        },
        onClick: function (e) {
            var $cell = $(this).closest('td'),
                $row = $cell.closest('tr.jqgrow'),
                $grid = $row.closest('table.ui-jqgrid-btable'),
                p,
                colModel,
                iCol;

            if ($grid.length === 1) {
                p = $grid[0].p;
                if (p) {
                    iCol = $.jgrid.getCellIndex($cell[0]);
                    colModel = p.colModel;
                    colModel[iCol].formatoptions.onClick.call($grid[0],
                        $row.attr('id'), $row[0].rowIndex, iCol, $cell.text(), e);
                }
            }
            return false;
        }
    });
}(jQuery));

I plan to place the code of the formatter and some other plugins to jqGrid on the github.

UPDATED: Free jqGrid extends the options of formatter: "showlink" (see the wiki article and the answer). So one don't need to use the formatter: "dynamicLink" in case of usage free jqGrid.

Midships answered 28/1, 2012 at 20:48 Comment(12)
Thank you. I tried this but quantity before edit start is returned. I updated question.Japeth
@Andrus: of cause if you use jsonReader having repeatitems: true you should rowData[iCol] instead of rowData.Stocks_valkogus. The formatter just forward the rowData parameter to url function and you use the notation which correspond the format of data. You wrote additionally about the problem with editing of data, but I don't understand what problem exactly you have. Could you describe the existing problem more exactly?Midships
User clicks in quantity column. This starts inline edit. User enters desired quantity and clicks add to cart link created using dynamicformatter. In this case dynamicformatter should pass entered quantity to url. Maybe dynamicformatter creation code should retrieve contents of input element which contains user entered quantity. Or is it better to save edited row and retrieve entered quantity after save ? Saving should not post data to server.Japeth
@Andrus: You use formatter here in a wrong way. It seems to me that you want use the link as the replacement of "Save" button of inline editing. In your case I would recommend you just use onClick part of formatter. On the onClick callback you can call saveRow to be sure that the values of the current editing rows are saved. You can additionally made any other calls of the server if you need do this additionally to the row saving.Midships
Save call causes error. Row from price list cannot saved to server from inline edit. How to implement this without saving data to server or should dummy save method in server called which returns succes on save? Is it ok to do this from method which constructs url?Japeth
@Andrus: Sorry, but I still not understand what you do and why the saving isn't work. In any way inside of onClick you know the rowid. So you can do full analyse of the row. You can easy get the current data from any <input> control too with about $('#' + $.jgrid.jqID(rowid) + '>td:nth-child(' + (iCol + 1) + '>input').val() where iCol should be the index of the quantity column.Midships
Save does not work since save method in server is not implemented and there is no need to implement it. I tried to use onClick but provided selector returns undefined. I updated question.Japeth
@Andrus: I still don't understand why yo use inline editing if you don't implement saving of the row. Moreover the Store/Details?... seems be pure HTTP get which will be cached on the client side and it can be that the server will be not called at the second time. You have to place revalidate caching in the HTTP headers of the Store/Details response. The current code of addToCartOnClick is not good because it will not work if you click the link in the row which is not in editing. In the code I see that you should use ')>input' instead of '>input'.Midships
I tried to add add to cart hyperlink to existing code whixh uses inline edit. Response header Cache-Control:private, s-maxage=0 seems automatically added by ASP .NET MVC so it is never cached. I added ) and then code starts working in inline edit, thank you!. I added check and if inline edit is not active, it posts 1 as quantity. onClick is not called if url is not specified. Should dummy url values used always, thisis not nice? How to make this to work from form edit also ?Japeth
@Andrus: default value of url is '#'. So if you just skip url definition or use url: '#' the onClick will be called. If you would use var $quantity = $('#' + $.jgrid.jqID(rowid) + '>td:nth-child(' + (iCol + 1) + ')') to get <td> of the 'Quantity' call. If $quantity.find('>input').length === 0 the cell is not in editing mode and both rowData.Stocks_valkogus and $quantity.text() get the value. if $quantity.find('>input').length === 1 the cell is in editing mode and you can get the value with respect of $quantity.find('>input').val(). It should work.Midships
Thank you very much. All this worked. If only onClick is used, hyperlink column looks like usual text column. How to add some formatting to it so that user has idea that this is clickable button/hyperlink, not usual column ?Japeth
It sound very strange. You can define in the cellValue function almost any HTML markup. For example you can prepend the call value with the icon by adding '<span class="ui-icon ui-icon-triangle-1-s" />' before the cell value or do some other thing. You can define any hover effects on the <a> by defining the corresponding CSS. So I don't understand why the hyperlink looks strange in your application. Probably the reason are some you current CSS styles.Midships

© 2022 - 2024 — McMap. All rights reserved.