Andrus Andrus - 3 months ago 12
jQuery Question

How to select row from ajax data

Free jqgrid contains button in each row. Clicking in button makes ajax call which returns customer list based on clicked row column value.

User can select customer from this data. Selected customer name and id should written to jqgrid row.

I tried code below but


Uncaught TypeError: Cannot read property 'rowIndex' of undefined


happens in line

var clickedId = $(this).closest('tr')[0].rowIndex,


when clicked in any place in seelction form.

How to fix this ? Application contains number of such selects from different data. Which is best way to implement them to avoid code repetition ?
table is created in javascript. Is it resonable/how to use some MVC partial view or other template for this ?
Can this code improved/refactored ?

Free jqgrid 4.13.3-pre, .NET 4.6, ASP.NET MVC, Bootstrap 3, jquery, jquuery UI are used.

Selection form is copied from bootstrap modal sample:

<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</div>
<div class="modal-body">
<table class='table table-hover table-striped'>
<thead>
<tr><td>Customer name</td><td>Customer Id</td></tr>
</thead>
<tbody></tbody>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">close without selection</button>
</div>
</div>
</div>
</div>

jqgrid colmodel:
formatter: "showlink",
formatoptions: {
onClick: function (options) {
var nimeosa = getColumnValue('customername', options.rowid);
if (nimeosa == null) {
return false;
}
$.ajax('api/Customers/FromRegister?' + $.param({ namepart: nimeosa }), {
type: 'GET',
dataType: 'json',
contentType: "application/json",
async: false
}).done(function (data, textStatus, jqXHR) {
var valik = "";
for (var i = 0; i < data.customerlist.length; i++) {
valik += '<tr><td>' + data.customerlist[i].customerName + '</td><td>' +
data.customerlist[i].customerId + '</td></tr>';
}
$('#exampleModal').on('show.bs.modal', function (event) {
$('.modal-body tbody').html(valik);
});

$('#exampleModal').on('click.bs.modal', function (event) {
// how to fix Uncaught TypeError: Cannot read property 'rowIndex' of undefined in this line:
var clickedId = $(this).closest('tr')[0].rowIndex, clickedElem = data.customerlist[clickedId];
$('#' + options.rowid + '_customername').val(clickedElem.customerName);
$('#' + options.rowid + '_customerid').val(clickedElem.customerId);
});
$('#exampleModal').modal();
);
return false;
}
}

// gets column value from jqgrid row
function getColumnValue(valjaNimi, rowId) {
var
iNimi = getColumnIndexByName($grid, valjaNimi),
$nimi = $('#' + rowId + '>td:nth-child(' + (iNimi + 1) + ')'),
nimiVal;

if ($nimi.find('>input').length === 0) {
// the cell is not in editing mode
nimiVal = $nimi.text();
}
else {
nimiVal = $nimi.find('>input').val();
}

if (nimiVal === undefined || nimiVal.trim() === '') {
alert('No value');
return null;
}
return nimiVal;
}


Update

I tried code from answer.
Rows are wider than bootstrap modal width.
Wide rows become wider than form:

enter image description here

How to fix this ?
How to force force rows to appear inside modal ?
How to create scrollbar if there are more rows than fits to screen ?

Answer

In order to get the values of the customer from the rows, you need to handle the click event of the <tr> element, not its parent modal. Since the rows are dynamically added, you need to handle this using event delegation.

$('#exampleModal tbody').on('click', 'tr', function() {
    var cells = $(this).children('td');
    $('#' + options.rowid + '_customername').val(cells.eq(0).text());
    $('#' + options.rowid + '_customerid').val(cells.eq(1).text());
    $('exampleModal').hide(); // assuming you want to close the modal
});

Note the above should be a separate script, but its not clear what options.rowid is and if that can be stored in a global variable or passed to the modal so it can be accessed in the above function (see following suggestion)

As a side note, some of your functions seem unnecessary (you keep reattaching the same events each time) and I believe the code can be just

// declare rowID as a global var and then in the above script you can use
// $('#' + rowID + '_customername').val(cells.eq(0).text());
var rowID;
var table = $('#exampleModal tbody'); // cache it

....
onClick: function (options) {
    rowID = options.rowid; // set the row ID
    ....
    $.ajax('api/Customers/FromRegister?' + $.param({ namepart: nimeosa }), {
        type: 'GET',
        dataType: 'json',
        contentType: "application/json",
        async: false
    }).done(function (data, textStatus, jqXHR) {
        table.empty(); // clear any existing rows
        $.each(data, function(index, item) {
            var row = $('<tr></tr>');
            row.append($('<td></td>').text(item.customerName ));
            row.append($('<td></td>').text(item.customerId));
            table.append(row);
        });
        $('#exampleModal').modal(); // display the mpday
    );
    return false;
}
Comments