如何使jqGrid基于行数据动态填充选项列表 [英] How to make jqGrid dynamically populate options list based on row data

查看:1700
本文介绍了如何使jqGrid基于行数据动态填充选项列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用jqrid版本3.8.1进行内联编辑,网格中的每一行都有几个要填充的下拉列表。当用户编辑行时,我需要执行一个AJAX查询来获取每个这些列表的值。我已经看到关于如何做到这一点的这篇文章。看来,这里的标准答案是 dataUrl buildSelect 功能。有一些问题我无法解释:


  1. 用户正在编辑的行的值必须为传入 dataUrl 值。例如,说每行包含一个称为SpecialValue的字段,第1行的SpecialValue = 100。行1的 dataUrl 字段将为 http://my.services.com?SpecialValue=100 。我该怎么做?


  2. 网格中的每一行都有大约10个需要填充的选择框。为了提高效率,我不想做10次单独的AJAX调用。做一个调用来获取所有的数据,将其分开,并相应地填充每个选择框会更好一些。那可能吗?我尝试在 onSelectRow 中执行此操作,但是网格结束时忽略了我放在那里的值(我猜测当编辑一行时触发的事件的顺序)




编辑:



阅读Oleg的答案后,更多的工作,很明显,使用 dataUrl buildSelect 不会对我有用。我正在使用的jqGrid版本不支持使用 dataUrl 我需要的方式。即使我不想为每个下拉列表发送多个单独的请求。



我决定在 gridComplete 触发将所有下拉列表所需的所有数据拉入单个JSON结构。然后当用户选择一行进行内联编辑时,我将填充该JSON结构中的行中的每个列表(下面的代码使用getSelectValuesFromJSON()函数) - 我不给它的定义,但是你可以对它进行映像我们有一些候选解决方案,但我并不满足于任何一个一个。



解决方案1 ​​



Inside onSelectRow ,我调用 editRow 覆盖 oneditfunc 以将数据从网格中取出我需要。假设 Field1 中的值需要将值放入 Field2 中的列表中。

  onSelectRow:function(index,status,e){
jQuery('#my_grid') .jqGrid('editRow',index,true,function(rowId){
var f1Val = $('#my_grid')jqGrid('getCell',index,'Field1');
var selectVals = getSelectValuesFromJSON(f1Val); //从先前加载的JSON结构获取数据
var select = $('#my_grid')。find('tr [id ='+ index +'] td [aria-描述by =my_grid_Field2] select');
_.each(selectVals,function(selectVal){
$(select).append($(< option>< / option> .attr(value,selectVal).text(selectVal));
});
});
}

这个工作,但我对这行的犹豫不决

  var select = $('#my_grid')find('tr [id ='+ index +' ] td [aria-descriptby =my_grid_Field2] select'); 

依赖于 aria描述的属性我不太了解。似乎很笨拙。



解决方案2



使用 beforeSelectRow 可以在用户选择一行时动态更改Field2列的模型。

  beforeSelectRow:function(index,e){
var f1Val = getGridCellValue('#my_grid',index,'Field1');
var values = getSelectValuesFromJSON(f1Val); //从先前加载的JSON结构获取数据
var valStr =;
_.each(values,function(value){
valStr + = value +:+ value +;
});
jQuery('#grid_pipes')。setColProp('Field2',{editoptions:{value:valStr}});
返回true;
}

这也可以,但我不知道这是否真的一个好主意。动态地更改这样的列的模型是否有效?如果用户同时选择了几行怎么办?列不是只有一个型号吗?这是什么意思?



要回答一些Oleg的问题, dataType 已被设置为使用$ .ajax将数据发布到服务器。我觉得我读过这不是推荐的方法了。我继承了这个代码,所以我不知道为什么它是这样做的,但是除非有一个非常令人信服的理由,否则它可能不会改变。



loadonce 布尔值未指定,所以我猜这意味着它默认为 false



这是列模型的缩写版本(没有什么不寻常的):

  colModel:[
{name:'PK',index:'PK',hidden:true,editable:true,sortable:true,search:true},
{name:'Field1'索引:'Field1',hidden:true,可编辑:true,sortable:true,search:true},
{name:'Field2',index:'Field2',sortable:false,editable:true,search: false,edittype:select,editoptions:{}},
{name:'Field3',index:'Field3',sortable:false,editable:true,search:false,edittype:select,editoptions :{}},
...
]


解决方案

你不会写出你目前使用的哪个版本的jqGrid,但是 dataUrl 可以定义为回调函数(rowid,value,name)参数,必须返回可以根据信息动态构建的URL。该功能以v4.5.3开头(参见)。您可以使用 getCell getRowData getLocalRow 回调从该列的另一列获取数据。因此,您可以比较容易地解决您的第一个问题。



您的第二个问题似乎与第一个问题绝对独立于第一个问题。最好在不同的帖子中分离这些问题,以便搜索引擎更好地索引信息,以便帮助其他人找到它。



没有简单的方法解决第二个问题,但可以肯定地提出一个解决方案,但是必须了解更多的细节你做什么以及如何做。你如何开始内联编辑(你使用 inlineNav formatter:actions或者你调用 editRow 直接)?哪个版本的jqGrid(直到版本4.7),免费jqGrid Guriddo jqGrid JS 你使用?如何在 colModel 中定义带有选择的列?您使用哪个数据类型?您是否使用 loadonce:true ?我建议您使用信息发布单独的问题。



更新:如果您必须使用旧版本jqGrid然后你不能动态地生成$ code> dataUrl ,但是因为你只需要添加 SpecialValue = 100 part该URL可以跟随我在许多旧答案中描述的技巧(第一个可能是这里,但是选择您可以使用 ajaxSelectOptions.data 来定义数据参数的属性名称的jQuery.ajax请求,问题只能你只能定义一个 ajaxSelectOptions.data 属性,所以你可以添加以下 jqGrid选项

  ajaxSelectOptions:{
data:{
SpecialValue:function(){
var rowid = $ myGri d.jqGrid(getGridParam,selrow);
return $ myGrid.jqGrid(getCell,rowidSpecialValue);
}
}
}

$ myGrid 类似于 $(#grid)



UPDATED:您在问题的更新部分中使用未知函数 getSelectValuesFromJSON getLookupValuesFromJSON 。这两个似乎都使用同步 Ajax请求,这不是很好。此外,您只为设置 editoptions.value Field2 而不是设置所有

  onSelectRow:function(rowid){
var $ myGrid = $(this);
$ .ajax({
url:someUrl,
dataType:json;
data:{
specialValue:$ myGrid.jqGrid(getCell ,rowid,Field1)
},
success:function(data){
//例如响应数据有格式:
// {Field2:[ v1,v2,...,Field3:[v3,v4,...]}
var filed,str;
for(filed in data){
if(data.hasOwnProperty(filed)){
str = $ .map(data [filed],function(item){
return item +:+ item
})。join(;);
$ myGrid.jqGrid(setColProp,提交,{
editoptions:{
value:str
}
} );
}
}
$ myGrid.jqGrid(editRow,rowid,true);
}
});
}

然而,解决方案2更接近于我推荐的。是否使用 onSelectRow beforeSelectRow 之前并不重要。您可以向服务器发送异步 Ajax请求,该服务器返回所有选择的信息。 从服务器获取响应 success 回调之间)可以设置 editoptions.value 为所有选择,只有这样才可以开始 editRow 。在这样的方式,您将确保该行的编辑将在所有选择中使用行特定选项。



其他一些备注。我建议您验证网格中的 gridview:true 选项。此外,我怀疑您填写网格不是完全正确的方式,因为您已隐藏 PK 列,并使用索引替代 rowid 作为 beforeSelectRow onSelectRow 的第一个参数。非常重要的是要了解,jqGrid 的当前实现始终在每行上分配 id 属性(< tr> 元素)。所以您必须在每个输入数据项目中提供 id 信息。如果您希望将id信息显示给用户(并且因此使用主键在 colModel 中列),那么您应该只包括 key:true 列定义中的属性。例如,您可以将 key:true 添加到 PK 列的定义,因此您将具有 (或 index 在您的情况下)与 PK 相同的值。它简化了代码的许多部分。例如,jqGrid在向服务器的编辑请求中发送 id 参数。请求中有 PK 是实用的。此外,如果您使用 repeatitems:false 格式的 jsonReader ,则可以包含 id:PK jsonReader 中,而不是隐藏 PK 列。它通知jqGrid从 PK 获得rowid。 jqGrid将在 id 属性< tr> PK >而不需要额外的< td style =display:none> 与网格中的相同信息。



最后一句话。我将严格建议您将复古版本jqGrid 3.8.1更新到更新版本,例如免费jqGrid 。即使您不使用功能(如 Font Awesome ),您将具有性能优势,而现代网络浏览器的外观将看起来更好。你应该明白jqGrid 3.8.1是用旧(和慢jQuery 1.4.2)测试的。与Internet Explorer 8一起使用的版本作为最新的IE版本(IE9于2011年3月稍后发布),更加面向IE6 / IE7。现代Chrome / Firefox / Safari的外观可能不好。是你想要的吗?


I am using jQrid version 3.8.1 with inline editing and each row in the grid has several dropdown lists to populate. When the user edits the row, I need to do an AJAX query to get the values for each of these lists. I've seen this post regarding how to do that. It appears that the dataUrl and buildSelect features are the standard answer here. There are a few issues I can't figure out though:

  1. The row the user is editing has a value that must be passed into the dataUrl value. For example, say each row contains a field called "SpecialValue" and that for row 1, SpecialValue = 100. The dataUrl field for row 1 would be "http://my.services.com?SpecialValue=100". How do I do that?

  2. Each row in the grid has about 10 select boxes that need to be populated. For efficiency reasons, I don't want to make 10 separate AJAX calls. It would be much better to make one call to get all the data, split it up, and fill each select box accordingly. Is that possible? I tried doing this inside onSelectRow but the grid ended up ignoring the values I put in there (I'm guessing do the ordering of the events that fire when you edit a row).

Edit:

After reading Oleg's answers and working on it more, it's clear to me that using dataUrl and buildSelect are not going to work well for me. The version of jqGrid I'm using doesn't support using dataUrl the way I would need. And even if it did I don't want to send multiple separate requests for each dropdown list.

I've decided to do one request when gridComplete fires to pull all the data needed for all dropdown lists into a single JSON structure. Then when the user selects a row to do inline editing, I will populate each list in the row from that JSON structure (the code below uses the getSelectValuesFromJSON() function for that--I don't give its definition but you can imaging it looks through the structure and gets an appropriate list of values to but in the list box).

I have a few candidate solutions but I'm not 100% happy with either one.

Solution 1:

Inside onSelectRow, I call editRow overriding the on oneditfunc to get the data out of the grid that I need. Assume that the value in Field1 is required to get the values to be put into the list in Field2.

onSelectRow: function (index, status, e) {
    jQuery('#my_grid').jqGrid('editRow', index, true, function(rowId) {
        var f1Val = $('#my_grid').jqGrid('getCell', index, 'Field1');
        var selectVals = getSelectValuesFromJSON(f1Val); //gets data out of previously loaded JSON structure
        var select = $('#my_grid').find('tr[id="' + index + '"] td[aria-describedby="my_grid_Field2"] select');
        _.each(selectVals, function(selectVal) {
            $(select).append($("<option></option>").attr("value", selectVal).text(selectVal));
        });
    });
}

This works but I'm hesitant about the line

var select = $('#my_grid').find('tr[id="' + index + '"] td[aria-describedby="my_grid_Field2"] select');

which relies on this aria-describedby attribute that I don't know much about. Seems hacky and brittle.

Solution 2:

Make use of beforeSelectRow to dynamically change the model of the Field2 column when the user selects a row.

beforeSelectRow: function(index, e) {
    var f1Val = getGridCellValue('#my_grid', index, 'Field1');
    var values = getSelectValuesFromJSON(f1Val); //gets data out of previously loaded JSON structure
    var valStr = "";
    _.each(values, function(value) {
        valStr += value + ":" + value + ";"
    });
    jQuery('#grid_pipes').setColProp('Field2', { editoptions: { value: valStr } });
    return true;
}

This also works but I'm not sure about whether or not this is really a good idea. Is it valid to dynamically change the model of a column like that? What if the user has several rows selected at the same time? Isn't there only one model for a column? What would that mean?

To answer some of Oleg's questions, the dataType has been set to a function that uses $.ajax to post data to the server. I think I read that's not the recommended approach anymore. I inherited this code so I'm not sure why it was done that way but it probably won't change unless there is a really compelling reason.

The loadonce boolean is not specified so I guess that means it defaults to false.

Here is an abbreviated version of the column model (nothing terribly out of the ordinary):

colModel: [
    { name: 'PK', index: 'PK', hidden: true, editable: true, sortable: true, search: true },
    { name: 'Field1', index: 'Field1', hidden: true, editable: true, sortable: true, search: true },
    { name: 'Field2', index: 'Field2', sortable: false, editable: true, search: false, edittype: "select", editoptions: {} },
    { name: 'Field3', index: 'Field3', sortable: false, editable: true, search: false, edittype: "select", editoptions: {} },
    ...
]

解决方案

You don't wrote which version of jqGrid you use currently, but dataUrl can be defined as callback function with (rowid, value, name) parameters, which have to return the URL which you can build dynamically based on the information. The feature exist starting with v4.5.3 (see the line). You can use getCell, getRowData or getLocalRow inside of the callback to get the data from another columns of the row. Thus you can solve your first problem relatively easy.

You second question seems to me absolutely independent from the first one. It's better to separate such questions in different posts to allow the searching engine better to index the information and so to help other people to find it.

There are no simple way how to solve the second problem, but one can sure suggest a solution, but one have to know much more details what you do and how you do. How you start inline editing (do you use inlineNav, formatter: "actions" or you call editRow directly)? Which version of jqGrid (till version 4.7), free jqGrid or Guriddo jqGrid JS you use? How the columns with selects are defined in colModel? Which datatype you use and whether loadonce: true you use? I recommend you to post separate question with the information.

UPDATE: If you have to use old version of jqGrid then you can't generate dataUrl full dynamically, but because you need to add only SpecialValue=100" part to the URL you can follow the trick which I described in many my old answers (the first one was probably here, but the choice on property names which asked the user could be misunderstood). You can use ajaxSelectOptions.data which will define the data parameters of jQuery.ajax request. The problem only that you can define only one ajaxSelectOptions.data property. So you can add the following jqGrid option:

ajaxSelectOptions: {
    data: {
        SpecialValue: function () {
            var rowid = $myGrid.jqGrid("getGridParam", "selrow");
            return $myGrid.jqGrid("getCell", rowid, "SpecialValue");
        }
    }
}

($myGrid is something like $("#grid"))

UPDATED: You used unknown functions getSelectValuesFromJSON, getLookupValuesFromJSON in the updated part of your question. Both of there seems to use synchronous Ajax request which is not good. Moreover you set editoptions.value for only one Field2 instead of setting all selects.

onSelectRow: function (rowid) {
    var $myGrid = $(this);
    $.ajax({
        url: "someUrl",
        dataType: "json";
        data: {
            specialValue: $myGrid.jqGrid("getCell", rowid, "Field1")
        },
        success: function (data) {
            // for example response data have format:
            // { "Field2": ["v1", "v2", ...], "Field3": ["v3", "v4", ...] }
            var filed, str;
            for (filed in data) {
                if (data.hasOwnProperty(filed)) {
                    str = $.map(data[filed], function (item) {
                                return item + ":" + item
                            }).join(";");
                    $myGrid.jqGrid("setColProp", filed, {
                        editoptions: {
                            value: str
                        }
                    });
                }
            }
            $myGrid.jqGrid("editRow", rowid, true);
        }
    });
}

Nevertheless the "Solution 2" is more close to what I would recommend you. It's not really important whether to use onSelectRow or beforeSelectRow. You can make asynchronous Ajax request to the server which returns information for all select which you need. After you get the response from the server (inside of success callback) you can set editoptions.value for all selects and only then you can start editRow. In the way you will be sure that editing of the line will use row specific options in all select.

Some additional remarks. I recommend you to verify gridview: true option in the grid. Additionally I suspect that you fill the grid in not full correct way because you have hidden PK column and you use index instead of rowid as the first parameter of beforeSelectRow and onSelectRow. It's very important to understand that the current implementation of jqGrid always assign id attribute on every row (<tr> element) of the grid. So you have to provide id information in every item of input data. If you want to display the id information to the user (and so to have column in colModel with the primary key) then you should just include key: true property in the column definition. For example you can add key: true to the definition of PK column and so you will have rowid (or index in your case) with the same value like PK. It simplify many parts of code. For example jqGrid send id parameter in the editing request to the server. It's practical to have PK in the request. Moreover if you use repeatitems: false format of jsonReader the you can include id: "PK" in the jsonReader instead of having hidden PK column. It informs jqGrid to get rowid from PK. jqGrid will save PK in id attribute of <tr> and you will don't need to have additional <td style="display:none"> with the same information in the grid.

The last remark. I would strictly recommend you to update the retro version jqGrid 3.8.1 to some more recent version, for example to free jqGrid. Even if you would use no features (like Font Awesome for example) you will have performance advantages, and the look of modern web browsers will looks much better. You should understand the jqGrid 3.8.1 was tested with old (and slow jQuery 1.4.2). The version used with Internet Explorer 8 as the latest IE version (IE9 was published later in March 2011) and it's more oriented on IE6/IE7. The look in modern Chrome/Firefox/Safari can be bad. Is it what you want?

这篇关于如何使jqGrid基于行数据动态填充选项列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆