ExtJS 更改事件侦听器未能触发
Posted
技术标签:
【中文标题】ExtJS 更改事件侦听器未能触发【英文标题】:ExtJS Change Event Listener failing to fire 【发布时间】:2009-12-02 14:45:52 【问题描述】:http://twitter.com/jonathanjulian 要求我将这个问题作为一个问题发布到 *** 上,然后被其他几个人转发。我已经有一个丑陋的解决方案,但正在按要求发布原始问题。
所以这是背景故事。我们有一个庞大的数据库应用程序,它专门为客户端视图使用 ExtJS。我们正在为从远程存储加载的行视图使用 GridPanel (Ext.grid.GridPanel)。
在我们的每个界面中,我们还有一个 FormPanel (Ext.form.FormPanel) 显示允许用户从 GridPanel 创建或编辑记录的表单。 GridPanel 列绑定到 FormPanel 表单元素,因此当在 GridPanel 中选择记录时,所有值都会填充到表单中。
在每个表单上,我们都有一个表行 ID(主键)的输入字段,其定义如下:
var editFormFields = [
fieldLabel: 'ID',
id: 'id_field',
name: 'id',
width: 100,
readOnly: true, // the user cannot change the ID, ever.
monitorValid: true
/* other fields removed */
];
所以,这一切都很好。这适用于我们所有的应用程序。在构建新界面时,要求我们需要使用第三方文件存储 API,该 API 以加载在 IFrame 中的小网页形式提供界面。
我将 IFrame 代码放在了 FormPanel 的 html 参数中:
var editForm = new Ext.form.FormPanel(
html: '<div style="width:400px;"><iframe id="upload_iframe" src="no_upload.html" ></iframe></div>',
/* bunch of other parameters stripped for brevity */
);
所以,每当用户选择一条记录时,我需要将 IFrame 的 src 属性更改为我们正在使用的服务的 API URL。类似于http://uploadsite.com/upload?appname=whatever&id=$id_of_record_selected
我最初进入 id 字段(粘贴在上面)并添加了一个更改侦听器。
var editFormFields = [
fieldLabel: 'ID',
id: 'id_field',
name: 'id',
width: 100,
readOnly: true, // the user cannot change the ID, ever.
monitorValid: true,
listeners:
change: function(f,new_val)
alert(new_val);
/* other fields removed */
];
很好很简单,只是它只在用户专注于该表单元素时才有效。其余时间它根本没有开火。
对我已经过了最后期限而只需要它工作感到沮丧,我迅速实施了一个衰减轮询器来检查值。这是一个可怕的,丑陋的黑客。但它按预期工作。
我会在这个问题的答案中粘贴我丑陋的肮脏技巧。
【问题讨论】:
这是什么 ExtJS 版本? 2009 年发布的任何版本。:) 很久以前了。 【参考方案1】:"GridPanel 列绑定到 FormPanel 表单元素,以便 当一条记录被选中时 GridPanel,所有的值都是 填写在表单中。”
正如我从上面的引用中了解到的那样,rowclick
事件实际上是首先触发表单更改的原因。为避免轮询,这可能是监听的地方,并最终引发您的自定义更改事件。
【讨论】:
谢谢。这完美地工作。现在,如果我能自己在 ext 文档中找到它就好了。 :D 我将你标记为正确答案。 仅供参考,通常最好绑定到 SelectionModel 的更改事件而不是网格的单击事件。这样键盘导航将触发相同的处理程序。 很高兴你得到了答案,埃里克!【参考方案2】:这是我为解决这个问题所做的丑陋的黑客攻击:
var current_id_value = '';
var check_changes = function(offset)
offset = offset || 100;
var id_value = document.getElementById('id_field').value || '';
if ( id_value && ( id_value != current_id_value ) )
current_id_value = id_value;
change_iframe(id_value);
else
offset = offset + 50;
if ( offset > 2500 )
offset = 2500;
setTimeout(function() check_changes(offset); , offset);
;
var change_iframe = function(id_value)
if ( id_value )
document.getElementById('upload_iframe').src = 'http://api/upload.php?id=' + id_value;
else
document.getElementById('upload_iframe').src = 'no_upload.html';
setTimeout(function() check_changes(100); , 1500);
;
它不漂亮,但它有效。所有的老板都很高兴。
【讨论】:
【参考方案3】:如果您花一点时间阅读源代码,您会看到 Ext.form.Field 类仅在 onBlur 函数中触发该更改事件
【讨论】:
我阅读了源代码。我知道它为什么这样做。我只是原则上不同意这一点。我不应该求助于丑陋的黑客来获取表单字段中已更改的值。作为一个严肃的现代框架,应该有一些机制让我能够捕获这些信息。我担心(以及最初发布推文的原因)是我所做的 99% 的工作都能很快完成,为此我很感激。剩下的 1% 花费(平均(作为一个疯狂的猜测))我的时间多 1000%。 您可以使用 keyup/keydown/keypress(将 enableKeyEvents 设置为 true)侦听器然后检查值吗?可能比轮询选项略好。 这是个好主意,但不能保证用户会按下某个键。我们可能能够保证用户至少会触发一个点击事件,尽管我必须在正文级别捕获它以获取每个可能的点击场景。这是一个好主意(鼠标事件),我可能会尝试。好主意。 这样做是因为 W3C 是这样定义更改事件的。 “当控件失去输入焦点并且在获得焦点后其值已被修改时,会发生更改事件。此事件对 INPUT、SELECT 和 TEXTAREA 元素有效。” (w3.org/TR/DOM-Level-2-Events/events.html) 另外,关于“多出 1000% 的时间”的评论——难道没有任何框架可以这么说吗?您是否曾经使用过能够 100% 解决编码问题的框架?如果是这样,请给我它的链接;)以上是关于ExtJS 更改事件侦听器未能触发的主要内容,如果未能解决你的问题,请参考以下文章