0

I am using jQrid version 3.8.1 and I have a grid that displays information about cars. The jQgrid should is set up to display one car per row and one of the columns is a multi-select list that displays which types of seats the car is configured with. A car can have multiple seat types.

enter image description here

When the user edits a car row, it makes an ajax query to get all of the seats types available in the system and sticks them in the multi-select list. In addition to populating the list, it needs to also select the options already chosen for that car.

enter image description here

The values inside the Installed Seats column are not simple strings. They have both an ID and a string value. So the ID for "Wire mesh" might be 2883 and the value for "Composite" might be 29991. They are just unique numeric values (basically the primary key from the table they are stored in).

After the multi-select list is populated with all the appropriate Seat values, I need to select the ones that the car currently has installed (in the picture above it's "Steel" and "Wire frame"). I need to do this based on the seat IDs stored for that car. However, I don't know where these value are going to come from. The grid only stores the names for the seats, not the IDs. Hopefully there is a way to make it store both.

The column model looks like this:

colModel: [
    { name: 'Year', index: 'Year', editable: true, edittype: "select", editoptions: { multiple: true } },
    { name: 'Make', index: 'Make', editable: true, edittype: "select", editoptions: { multiple: true } },
    { name: 'Body', index: 'Body', editable: true, edittype: "select", editoptions: { multiple: true } },
    { name: 'Seats', index: 'Seats', editable: true, edittype: "select", editoptions: { multiple: true }, cellattr='is-seat-list="1"' }
]

Notice that the 'Seats' model has a cell attribute called is-seat-list. I'm using this to find the select box in the row inside the 'editRow' function.

The onSelectRow handler looks like this:

onSelectRow: function (index) {
    var curValues = $('#cargrid').getRowData(index);

    jQuery('#cargrid').jqGrid('editRow', index, true, function(rowId) {

        //when the user edits the row, query for all the seat types and fill in the list
        jQuery.ajax({
            url: '/getalltheseats',
            complete: function (allSeats, stat) {
                var list = $('#cargrid').find('tr[id="' + rowId + '"] td[is-seat-list="1"] select');
                var $list = $(list);

                //add the all seat types to the list, checking the ones that this car currently has selected
                _.each(allSeats, function(seat) {
                    var selected = '';
                    if(curValues['Seats'].indexOf(seat.ID) !== -1) //<-- what do I do here??
                        selected = 'selected';

                    $list.append($('<option ' + selected + '></option>').attr('value', seat.ID).text(seat.Name));
                });
            });
        });
    });
},

The important line is

if(curValues['Seats'].indexOf(seat.ID) !== -1)

I have the value of the row but it only contains the seat name, not the ID. The data returned from the ajax call contains each seat name and ID but the <option> elements don't contain the ID value so I don't know which ones to select in the list.

So the question is, what's the best way to make jqGrid store both the seat names and IDs so that when I create the list dynamically, I can check the <option>s for the seats that have been chosen for that car.

Note:
For various reasons the standard dataUrl and buildSelect features of jqGrid are not going to work for me, which is why I'm building the list on the fly in this manner.

Community
  • 1
  • 1
d512
  • 32,267
  • 28
  • 81
  • 107
  • You didn't wrote **which version of jqGrid you use**. Could we stay by the example with two autos and you prepare the full JSFiddle demo with the filled grid? The way with `dataUrl` and `buildSelect` would be preferred and it should work. It do exactly what you need: load the data and select the items from the editing row. If it not work then you should include the code and one will fix it. Additionally you can include at example of JSON response for `Seats` column from `dataUrl`. Something like `{{"ID": 123, "Name": "Steel"}, ...}`. It can be that you will be need to use `formatter: "select"` – Oleg May 15 '15 at 20:58
  • One see on the picture that you use multiselect plugin, but you didn't included the corresponding JavaScript code which show how and where in your code you initialize multiselect on the ` – Oleg May 15 '15 at 21:01
  • Argh! Forgot to include the jqGrid version again! I added it. – d512 May 15 '15 at 21:54
  • @Oleg, thanks for the input. I' not using dataUrl and buildSelect because they make a separate call for each cell and I don't want to make that many server calls. Also I think the version of jqGrid may not support adding query string parameters to the dataUrl value. Anyway, I probably will not rewrite it to use dataUrl/buildSelect at this point. You can see a previous post (http://stackoverflow.com/questions/29855762/how-to-make-jqgrid-dynamically-populate-options-list-based-on-row-data) that talks about why. I will put a jsfiddle together for you, but it's going to take a little while. – d512 May 15 '15 at 22:01
  • One can probably support the solution which use 3.8.1 and try to develop for IE5 or for Window 4.0, but the investments are too high. You need to write absolute another code as you need in modern version of jqGrid. About `dataUrl`: all depend on how many different properties exist for `Seats` column. You can load the data **before** you create the grid and then use `editoptions.value` and `formatter: "select"`. It should solve your problem. – Oleg May 15 '15 at 22:03
  • I understand your point, but there simply isn't time or budget to go through an upgrade of jqGrid right now. The entire web app is heavily based on it and upgrading would be a very disruptive endeavor at this point. If the answer is that jQgrid 3.8.1 simply won't support doing what I want to do, I guess that's how it will have to be. – d512 May 15 '15 at 22:46
  • The version 3.8.1 and many later versions (later as 4.6) are of cause out of support since long time, but I think that can still help you it you answer on the following questions: **How many different properties exist for Seats column?** Can one load **all the values** via Ajax **before** jqGrid will be created? You can create the grid inside of `success` callback of the ajax request. You can construct `value` parameter (in `editoptions`) for 'Seats' column and then create the grid. You should fill the grid data using **ID** values and use `formatter: "select"` additionally. – Oleg May 15 '15 at 22:54
  • @Oleg, I see what you're saying. Basically I would keep a cache of all the Seat values in the browser. There aren't too terribly man so that should probably be okay. But this is a single page web app and there are things the user can to do create more seat values in the application. So I would need a way to refresh the grid so it can pick up the new Seat values inside editoptions.values. Will calling grid.trigger("reloadGrid") achieve that? Or can you only set the editoptions.values the first time the grid is actually created? – d512 May 16 '15 at 01:12

1 Answers1

1

First of all you need additionally add formatter: "select" and to populate ID values in Seats column during filling of the grid. The formatter: "select" will decode the IDs and the corresponding Name value will be displayed to the user.

If you would use more recent version of jqGrid the you can use beforeProcessing callback created for the purpose. It allows to include all different ID/Name pairs in the server response for filling of the grid. It allows you to fill the information needed for the formatter: "select" directly in the main server response. You don't need to load the information before creating the grid.

If you use retro version of jqGrid (3.8.1) then I hope that you can still use the following trick. You can define userdata part of the server response defined as function. The outer elements of the server response root, page, total, records and userdata will be processed before the processing the main part with all items. It allows you to modify editoptions.value before it will be processed by formatter: "select".

For example the response from the server can looks like

{
    "page": 1,
    "total": 20,
    "records": 400,
    "userdata": {
        "seats": "29991:Composite;42713:Nappa leather;6421:Steel;2883:Wire mesh"
    },
    "rows": [
        {
            "year": 2007,
            "model": "Toyota/Camry",
            "body": "Sedan",
            "seats": "29991,6421"
        },
        {
            "year": 2057,
            "model": "BMW/Series 4",
            "body": "Sedan",
            "seats": "6421,2883"
        }
    ]
}

Inside of jsonReader you can define userdata which set userdata.seats as value of editoptions. You can use setColProp method for example to do this.

In the way you will be able to implement all your requirements.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Oleg, you did it again. Are you the king of customer support or what Thank you so much. I'm having trouble getting it to work with the jQuery multiselect, but I can create another post about that issue. – d512 May 16 '15 at 22:58