我正在使用表单编辑。表单中有两个选择框。一个选择框是国家,另一个选择框是州。州选择框取决于所选国家,并将动态填充。例如:
国家:
US (option value=1)
UK (option value=2)
美国的状态:
Alabama (option value=1)
California (option value=2)
Florida (option value=3)
Hawaii (option value=4)
英国的状态:
London (option value=5)
Oxford (option value=6)
如您所见,英国的州 ID 以 5 开头。当我编辑包含 Country id=2 (UK) 和 State id=6 (Oxford) 的记录时,编辑表单将正确显示 - Country 是 UK,State 是 Oxford。但是如果你下拉状态选择框选项文本是正确的(它显示伦敦牛津)但是选项值将从 0 开始。应该正确的是选项值应该从 5 开始。
如果您选择并将国家/地区下拉框更改为美国,然后再次更改回英国,选项值将被正确填充(从 5 开始)。
我的问题是,当加载编辑表单时,我们如何根据编辑框中的国家/地区使用正确的选项值填充州的选择框?
最佳答案
您的问题的答案在一定程度上取决于您收到“美国所在州”和“英国所在州”下显示的信息的来源。 jqGrid 支持两种可能性:1) editoptions 的 value 参数的使用2) editoptions的dataUrl和buildSelect参数的使用.在本地编辑或可能选项列表是静态的情况下,第一种方法是最好的方法。第二个选择将用于这种情况,即根据 AJAX 请求从数据库中获取有关州、国家和某个国家/地区的州的信息。我在示例中描述了使用 value 参数以不依赖于服务器组件的解决方案。在使用dataUrl 和buildSelect 的情况下,实现的大部分部分是相同的。
我做了 the live example展示您的需求。
主要问题是 editoptions 的 value 在初始化时仅使用一次。 dataInit 内部函数可以覆盖值,但是在第一个带有国家的选择/下拉框中的值发生变化后,第二个带有状态的选择/下拉框必须手动重建。为此,您必须了解,select HTML 元素具有由行 ID“_”和列名称构造的 ID:rowId +“_State”。此外,重要的是,editoptions 的 value 必须重置为初始值,以便任何状态 id 都可以解码为状态名称。
这是来自 the example 的代码:
var countries = { '1': 'US', '2': 'UK' };
var states = { '1': 'Alabama', '2': 'California', '3': 'Florida', '4': 'Hawaii', '5': 'London', '6': 'Oxford' };
var statesOfCountry = {
1: { '1': 'Alabama', '2': 'California', '3': 'Florida', '4': 'Hawaii' },
2: { '5': 'London', '6': 'Oxford' }
};
var mydata = [
{ id: '0', Country: '1', State: '1', Name: "Louise Fletcher" },
{ id: '1', Country: '1', State: '3', Name: "Jim Morrison" },
{ id: '2', Country: '2', State: '5', Name: "Sherlock Holmes" },
{ id: '3', Country: '2', State: '6', Name: "Oscar Wilde" }
];
var lastSel = -1;
var grid = jQuery("#list");
var resetStatesValues = function () {
grid.setColProp('State', { editoptions: { value: states} });
};
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name: 'Name', width: 200 },
{ name: 'Country', width: 100, editable: true, formatter: 'select',
edittype: 'select', editoptions: {
value: countries,
dataInit: function (elem) {
var v = $(elem).val();
// to have short list of options which corresponds to the country
// from the row we have to change temporary the column property
grid.setColProp('State', { editoptions: { value: statesOfCountry[v]} });
},
dataEvents: [
{
type: 'change',
fn: function(e) {
// To be able to save the results of the current selection
// the value of the column property must contain at least
// the current selected 'State'. So we have to reset
// the column property to the following
//grid.setColProp('State', { editoptions:{value: statesOfCountry[v]} });
//grid.setColProp('State', { editoptions: { value: states} });
resetStatesValues();
// build 'State' options based on the selected 'Country' value
var v = parseInt($(e.target).val(), 10);
var sc = statesOfCountry[v];
var newOptions = '';
for (var stateId in sc) {
if (sc.hasOwnProperty(stateId)) {
newOptions += '<option role="option" value="' +
stateId + '">' +
states[stateId] + '</option>';
}
}
// populate the new
if ($(e.target).is('.FormElement')) {
// form editing
var form = $(e.target).closest('form.FormGrid');
$("select#State.FormElement", form[0]).html(newOptions);
} else {
// inline editing
var row = $(e.target).closest('tr.jqgrow');
var rowId = row.attr('id');
$("select#" + rowId + "_State", row[0]).html(newOptions);
}
}
}
]
}
},
{
name: 'State', width: 100, editable: true, formatter: 'select',
edittype: 'select', editoptions: { value: states }
}
],
onSelectRow: function (id) {
if (id && id !== lastSel) {
if (lastSel != -1) {
resetStatesValues();
grid.restoreRow(lastSel);
}
lastSel = id;
}
},
ondblClickRow: function (id, ri, ci) {
if (id && id !== lastSel) {
grid.restoreRow(lastSel);
lastSel = id;
}
resetStatesValues();
grid.editRow(id, true, null, null, 'clientArray', null,
function (rowid, response) { // aftersavefunc
grid.setColProp('State', { editoptions: { value: states} });
});
return;
},
editurl: 'clientArray',
sortname: 'Name',
height: '100%',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
pager: '#pager',
caption: "Demonstrate dependend select/dropdown lists (edit on double-click)"
}).jqGrid('navGrid','#pager',
{ edit: true, add: true, del: false, search: false, refresh: false },
{ // edit options
recreateForm:true,
onClose:function() {
resetStatesValues();
}
},
{ // add options
recreateForm:true,
onClose:function() {
resetStatesValues();
}
});
已更新:我更新了上面的代码,使其在表单编辑时也能正常工作。可以直播看here .因为 jqGrid 不支持表单编辑的本地编辑,所以我无法测试代码。尽管如此,我还是希望我已充分利用所需的更改。
更新 2:我扩展了上面的代码以支持
新版本的演示是here .您在下面找到的演示的修改代码:
var countries = { '1': 'US', '2': 'UK' },
//allCountries = {'': 'All', '1': 'US', '2': 'UK'},
// we use string form of allCountries to have control on the order of items
allCountries = ':All;1:US;2:UK',
states = { '1': 'Alabama', '2': 'California', '3': 'Florida', '4': 'Hawaii', '5': 'London', '6': 'Oxford' },
allStates = ':All;1:Alabama;2:California;3:Florida;4:Hawaii;5:London;6:Oxford',
statesOfUS = { '1': 'Alabama', '2': 'California', '3': 'Florida', '4': 'Hawaii' },
statesOfUK = { '5': 'London', '6': 'Oxford' },
// the next maps contries by ids to states
statesOfCountry = { '': states, '1': statesOfUS, '2': statesOfUK },
mydata = [
{ id: '0', country: '1', state: '1', name: "Louise Fletcher" },
{ id: '1', country: '1', state: '3', name: "Jim Morrison" },
{ id: '2', country: '2', state: '5', name: "Sherlock Holmes" },
{ id: '3', country: '2', state: '6', name: "Oscar Wilde" }
],
lastSel = -1,
grid = $("#list"),
removeAllOption = function (elem) {
if (typeof elem === "object" && typeof elem.id === "string" && elem.id.substr(0, 3) !== "gs_") {
// in the searching bar
$(elem).find('option[value=""]').remove();
}
},
resetStatesValues = function () {
// set 'value' property of the editoptions to initial state
grid.jqGrid('setColProp', 'state', { editoptions: { value: states} });
},
setStateValues = function (countryId) {
// to have short list of options which corresponds to the country
// from the row we have to change temporary the column property
grid.jqGrid('setColProp', 'state', { editoptions: { value: statesOfCountry[countryId]} });
},
changeStateSelect = function (countryId, countryElem) {
// build 'state' options based on the selected 'country' value
var stateId, stateSelect, parentWidth, $row,
$countryElem = $(countryElem),
sc = statesOfCountry[countryId],
isInSearchToolbar = $countryElem.parent().parent().parent().hasClass('ui-search-toolbar'),
//$(countryElem).parent().parent().hasClass('ui-th-column')
newOptions = isInSearchToolbar ? '<option value="">All</option>' : '';
for (stateId in sc) {
if (sc.hasOwnProperty(stateId)) {
newOptions += '<option role="option" value="' + stateId + '">' +
states[stateId] + '</option>';
}
}
setStateValues(countryId);
// populate the subset of contries
if (isInSearchToolbar) {
// searching toolbar
$row = $countryElem.closest('tr.ui-search-toolbar');
stateSelect = $row.find(">th.ui-th-column select#gs_state");
parentWidth = stateSelect.parent().width();
stateSelect.html(newOptions).css({width: parentWidth});
} else if ($countryElem.is('.FormElement')) {
// form editing
$countryElem.closest('form.FormGrid').find("select#state.FormElement").html(newOptions);
} else {
// inline editing
$row = $countryElem.closest('tr.jqgrow');
$("select#" + $.jgrid.jqID($row.attr('id')) + "_state").html(newOptions);
}
},
editGridRowOptions = {
recreateForm: true,
onclickPgButtons: function (whichButton, $form, rowid) {
var $row = $('#' + $.jgrid.jqID(rowid)), countryId;
if (whichButton === 'next') {
$row = $row.next();
} else if (whichButton === 'prev') {
$row = $row.prev();
}
if ($row.length > 0) {
countryId = grid.jqGrid('getCell', $row.attr('id'), 'country');
changeStateSelect(countryId, $("#country")[0]);
}
},
onClose: function () {
resetStatesValues();
}
};
grid.jqGrid({
data: mydata,
datatype: 'local',
colModel: [
{ name: 'name', width: 200, editable: true },
{ name: 'country', width: 100, editable: true, formatter: 'select', stype: 'select', edittype: 'select',
searchoptions: {
value: allCountries,
dataInit: function (elem) { removeAllOption(elem); },
dataEvents: [
{ type: 'change', fn: function (e) { changeStateSelect($(e.target).val(), e.target); } },
{ type: 'keyup', fn: function (e) { $(e.target).trigger('change'); } }
]
},
editoptions: {
value: countries,
dataInit: function (elem) { setStateValues($(elem).val()); },
dataEvents: [
{ type: 'change', fn: function (e) { changeStateSelect($(e.target).val(), e.target); } },
{ type: 'keyup', fn: function (e) { $(e.target).trigger('change'); } }
]
}},
{ name: 'state', width: 100, formatter: 'select', stype: 'select',
editable: true, edittype: 'select', editoptions: { value: states },
searchoptions: { value: allStates, dataInit: function (elem) { removeAllOption(elem); } } }
],
onSelectRow: function (id) {
if (id && id !== lastSel) {
if (lastSel !== -1) {
$(this).jqGrid('restoreRow', lastSel);
resetStatesValues();
}
lastSel = id;
}
},
ondblClickRow: function (id) {
if (id && id !== lastSel) {
$(this).jqGrid('restoreRow', lastSel);
lastSel = id;
}
resetStatesValues();
$(this).jqGrid('editRow', id, {
keys: true,
aftersavefunc: function () {
resetStatesValues();
},
afterrestorefunc: function () {
resetStatesValues();
}
});
return;
},
editurl: 'clientArray',
sortname: 'name',
ignoreCase: true,
height: '100%',
viewrecords: true,
rownumbers: true,
sortorder: "desc",
pager: '#pager',
caption: "Demonstrate dependend select/dropdown lists (inline editing on double-click)"
});
grid.jqGrid('navGrid', '#pager', { del: false }, editGridRowOptions, editGridRowOptions);
grid.jqGrid('filterToolbar', {stringResult: true, searchOnEnter: true, defaultSearch : "cn"});
更新 3:您将找到演示代码的最新版本 here .
关于javascript - jqgrid 在编辑框中不正确选择下拉选项值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4469650/
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。
我在OSX上(如果重要的话)。如果我使用RVM安装Ruby,它会默认将Bundler安装到@globalgemset假设我想要一个不同版本的bundler。我假设我需要做的就是执行geminstallbundler--version但是,这会将bundler安装到默认gemset并且RVM不会为其设置路径。因此,如果我键入bundler,它仍会启动一个与Ruby一起安装到@global中的bundler两个问题:如何将bundler安装到@globalgemset。将bundler安装到@globalgemset中的模式是否正确,或者我遗漏了什么 最佳答案
什么Ruby或RailsDSL会将字符串"mccdougal"格式化为"McDougal",同时留下字符串"McDougal"原样?将titleize传递给"McDougal"结果如下:"McDougal".titleize#=>"McDougal" 最佳答案 据我所知,没有可以处理这种情况的Rails助手。这是一个非标准的边缘案例,需要特殊处理。但是,您可以创建自定义字符串变形。您可以将这段代码放入初始化程序中:ActiveSupport::Inflector.inflections(:en)do|inflect|inflect.
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
对于用户模型,我有一个过滤器来检查用户的预订状态,该状态由整数值(0、1或2)表示。UserActiveAdmin索引页上的过滤器是通过以下代码实现的:filter:booking_status,as::select然而,这会导致下拉选项为0、1或2。当管理员用户从下拉列表中选择它们时,我更愿意自己将它们命名为“未完成”、“待定”和“已确认”之类的名称。有没有办法在不改变booking_status在模型中的表示方式的情况下做到这一点? 最佳答案 假设booking_status是模型中的枚举字段,您可以使用:过滤器:booking