Прослушиватель событий изменения ExtJS не срабатывает

меня попросили опубликовать это как вопрос о StackOverflow по http://twitter.com/jonathanjulian который затем был ретвитирован несколькими другими людьми. У меня уже есть уродливое решение, но я публикую исходную проблему по запросу.

вот такая история. У нас есть массивное приложение базы данных, которое использует ExtJS исключительно для просмотра на стороне клиента. Мы используем GridPanel (Ext.сетка.GridPanel) для вида строки, загруженного с удаленного магазин.

в каждом из наших интерфейсов у нас также есть FormPanel (Ext.форма.FormPanel) отображение формы, которая позволяет пользователю создавать или редактировать записи из GridPanel. Столбцы GridPanel привязаны к элементам формы FormPanel, поэтому при выборе записи в GridPanel все значения заполняются в форме.

В каждой форме у нас есть поле ввода для идентификатора строки таблицы (первичный ключ), который определяется как таковой:

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 хранения файлов, который предоставляет интерфейс в виде небольшой веб-страницы, загружаемой в IFrame.

Я поместил код IFrame внутри html-параметра FormPanel:

var editForm = new Ext.form.FormPanel({
   html: '<div style="width:400px;"><iframe id="upload_iframe" src="no_upload.html" width="98%" height="300"></iframe></div>',
   /* bunch of other parameters stripped for brevity */
});

Итак, всякий раз, когда пользователь выбирает запись, мне нужно изменить атрибут src IFrame на URL API службы, которую мы используем. Что-то вроде 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 */
];

приятно и просто, за исключением того, что он работал только тогда, когда пользователь был сосредоточен на этом элементе формы. В остальное время он вообще не стрелял.

разочарованный тем, что я прошел крайний срок и просто нуждался в нем, чтобы работать, я быстро реализовал распадающийся poller, который проверяет значение. Это ужасный, уродливый взлом. Но это работает, как и ожидалось.

я вставлю свой уродливый грязный хак в ответ на этот вопрос.

3 ответов


" столбцы GridPanel привязаны к элементы формы FormPanel так, чтобы когда запись выбрана в GridPanel, все значения заполняется в форме."

Как я понимаю из приведенной выше цитаты,rowclick событие-это то, что на самом деле вызывает изменения в форму, в первую очередь. Чтобы избежать опроса, это может быть место для прослушивания и, в конечном итоге, для вашего пользовательского события изменения.


вот уродливый хак, который я сделал для решения этой проблемы:

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);
};

это не очень красиво, но это работает. Все боссы счастливы.


Если бы вы воспользовались моментом, чтобы прочитать Источник, вы бы увидели, что Ext.форма.Класс поля только запускает событие изменения в функции onBlur