ExtJS Hack: Dynamic ComboBox & Remote On-Demand Loading With Local Filtering extjs���J�G�ʺA�զX�����{���ѨD�[��P��a�L�o
In ExtJS you can create ComboBox which loads data from the server.�bextjs�z�i�H�Ы�ComboBox���A�䤤���ƾڱq�A�Ⱦ��C You can also code so that new data is loaded from the server in response to an event like changing selection of another ComboBox.�z�]�i�H�N�X�A�H�K�s���ƾڥ[��A�q�A�Ⱦ����T���ƥ�@�ˡA���_�ܤƪ��t�@�ؿ��ComboBox���C However it also means that the filtering is done remotely which is slow.���L�A�o�]�N��ۡA�L�o�O�����{�o�O�i�i�w�C�C
In ExtJS ComboBox automatic filtering is a nifty capability where the ComboBox items are automatically filtered to show only the values which matches the text you typed so far.�bextjs ComboBox���۰ʹL�o�O�@�Ӻ}�G����O�A�pComboBox�������ط|�۰ʹL�o�A�u��ܪ�����[�ۤǰt�z�ҿ�J����r�ܤ��C It can also auto-fill the rest for you.���]�i�H�۰ʶ�J�A��l�����A�C This powerful capability comes at a price for remote mode.�o�ӱj�j����O�A�b�@�ӻ�欰���{�Ҧ��C Every time the data is filtered by sending a query to the server which can be slower than local query.�C�@�����ƾڬO�L�o�o�e�d�ߨ�A�Ⱦ��i�C�A���a�d�ߡC
In many use cases the full data is already on the client side, fetched during the initial loading of the ComboBox.�b�\�h���p�U�ϥΪ������ƾڤw�g�b�Ȥ�ݡA�o�j�A�b�̪쪺�[��ComboBox���C Subsequent filtering can be easily done on the client side.�H�᪺�L�o�i�H�ܮe���a���b�Ȥ�ݡC Let's see how we can solve it.��ڭ̬ݬݧڭ̦p�����ѨM�o�Ӱ��D�C
Update: I have also filed a��s�G�ڤ]����F�@�� defect�ʳ� in ExtJS forum to hopefully incorporate the functionality in the core with suggested solutions.�bextjs�¡A�Ʊ�ǤJ���\��A�b�֤P��ij���ѨM��k�C The defect details has been provided at the end of this post.�ʳ����ԲӸ�Ƥw���Ѧb���멳��C
The intuitive approach to this problem is to load the ComboBox on an event handler after setting the baseParams of the store with appropriate parameters.���[����k�A�o�Ӱ��D�O��JComboBox����@�Өƥ�B�z�{�ǫ�A�q�wbaseparams���ө��P�A�?�ѼơC This works in remote mode but not in local mode.�o�Ӥu�{�b�����Ҧ��A�Ӥ��O�b���a�Ҧ��C Now you want to set the ComboBox to local mode because you want to implement local filtering, right?�{�b�A�z�n�]�mComboBox���A�H���a�Ҧ��A�]���z�n����a��L�o�A�藍��H
The solution is far from obvious.�ѨM����k�O������ө������C In local mode ComboBox clears the filters of the store which in turn replaces the data in the store with the stored, and obviously stale, snapshot.�b���a�Ҧ�ComboBox���M���L�o�����ө��A�q�Ө�N�F�ƾڪ��s�x�P�s�x�A�é��㳯�¡A�ַӡC To solve this you must call combo.store.updateSnapshot() after the combo.store.load() call.���F�ѨM�o�ӡA�A��������combo.store.updatesnapshot �] �^��A combo.store.load �] �^�եΡC
Now where can you get this function?�{�b�A�b���̥i�H�o��o�ӥ\��H Oh yes�K�@�O�K
Ext.data.Store.prototype.updateSnapshot = function() { this.snapshot = this.data; } ext.data.store.prototype.updatesnapshot =��ơ] �^ �] this.snapshot = this.data ; �^ The on demand loading is accomplished by keeping the data in local mode and then loading the store once (use a boolean to check) on beforequery event handler.�ӻݨD���t��O�q�L�O��ƾڦb���a�Ҧ��A�M��[��s�x�@���]�ϥΤ@�ӥ����ˬd�^��beforequery�ƥ�B�z�{�ǡC You have to use updateSnapshot() function after the load as explained above.�z�����ϥ�updatesnapshot �] �^��ƫ�t��p�H�W�Ҹ������C
Use cases �ϥήר�
Let's first look at the use cases which I am sure many will agree with.��ڭ̥�ݬݨϥα��p�U�A�ڬ۫H�ܦh�H���|�P�N�C1. 1 �C I want to load a ComboBox on demand.�ڷQ�t��NComboBox���ݨD�C I have very large number of columns in a grid, each of which has a ComboBox to help selecting a value.�ڦ��D�`�j���ƥئC�b�@�Ӻ���A�䤤�C�@�ӲզX�A�H���U��ܤ@�ӭȡC I don't want to load all the data upfront as that slows down the initial loading.�ڤ��Q�t��Ҧ��ƾڪ��e�����˩�w�A��B�[��C So I want to load the data when the ComBox drop-down is clicked.�ҥH�ڷQ�[��ƾڮɡA combox�U�Ԧ��I���C I can easily do that in remote mode but the downside is that the filtering functionality asks the server for filtering.�ڥi�H�ܮe�����A�b�����Ҧ��A����I�O�A�ӹL�o�\��A�o�ǥ\��n�D�A�Ⱦ��L�o�C The data I fetched is fixed and it is already on the client, so there is no justification for bothering the server.�Ӽƾ�I�o�j�A�o�O�@�өT�w���A�o�O�w�g�b�Ȥ�ݡA�ҥH�O�S���D�z���x�Z�A�Ⱦ��C
2. 2 �C An alternative scenario is when you have a dynamically loaded ComBox.�t�@�ر��p�O��A���@�ӰʺA�[��combox �C You would still like to do local filtering, when the data has been fully loaded, for better performance.�z���Q�o�˰����a�L�o�A��ƾڤw����A��n����{�C This might be the one you can better associate with.�o�i��O�@�ӱz�i�H��n�a�pô�C
Defect �ʳ�
My solution was to keep the ComboBox in local mode but load the store on first access.�ڪ��ѨM��k�O��ComboBox���b��a���Ҧ��A��t��������X�ݡC This works perfectly in remote mode for the dynamically loading case.�o�Ӥu�{�����i�H�b�����Ҧ����ʺA�[��p�C However it doesn't work when the mode is local.���L���S���u�@�ɪ��Ҧ��A�O���a�ӮסC In local mode the doQuery() calls clearFilter() which replaces the new data in the store with old stale snapshot data.�b���a�Ҧ�doquery �] �^�ե�clearfilter �] �^��N�A�s���ƾڦs�x�P�³��ª��ַӼƾڡCWhat is needed is to replace the snapshot data in this case with the current data in the store after a successful reload.�һݭn���O�A�H��N�ַӼƾڦb�o�ر��p�U�A�P�ثe���ƾڦs�x��A�@�Ӧ��\�����s�[��C
The real defect is that in this case clearFilter() shouldn't replace the store with old snapshot when the store has been refreshed by a call to load.�u�����ʳ��O�A�b�o�ر��p�Uclearfilter �] �^������N�s�x�P�ª��ַӮɡA�ө��w�Q��s�A�ѥ��q�ܵ��t��C
Solution �ѨM���
My solution was to create a method for this in ComboBox:�ڪ��ѨM��O�Ыؤ@�Ӥ�k�A�o�bComboBox���G
Code:�N�X�GExt.data.Store.prototype.updateSnapshot = function() { this.snapshot = this.data }ext.data.store.prototype.updatesnapshot =��ơ] �^ �] this.snapshot = this.data �^And then call this method after loading the ComboBox.�M��եΦ���k��A�[��ComboBox���C
The solution works but I am not fully happy as it isn't elegant.�ѨM�u�{�A��ڨä������P�찪���A�]���o�O���u�����C Looking forward to hear a better idea in solving this problem.���ݵ�ť���n���Q�k�A�b�ѨM�o�Ӱ��D�C
Additional Thoughts �B�~�����
I think there should be a way for clearFilter() to recognize when new data has been loaded versus when filtered data has been loaded for the old data.�ڻ{�����Ӧ��@�ӳ~�|clearfilter �] �^�ӻ{�A��s���ƾڤw�[��Ȩ�ɡA�L�o�ƾڤw�Q��J�¼ƾڡC Both cases uses load().�o��ر��p�U�ϥέt��] �^ �C
The solution could be a new configuration parameter to load() which clearFilter() looks for and processes, if available.�ӸѨM��ץi��O�@�ӷs���t�m�Ѽƥ[��] �^ clearfilter �] �^�d��M�i�{�A�p�G�i�ΡC
Filed under���_�U Ajax���J�� , �A Browser�s�� , �A Headline News�Y��s�D , �A How To�p�� , �A Javascript JavaScript�� , �A Programming�s�{ , �A Tech Note�N���� , �A Web���� , �A Web 2.0 Web 2.0�� | |
| |
RSS 2.0 2.0 | |
Trackback Trackback��踪 this Article |���峹|
Email this Article�q�l�l�峹
You may also like to read�z�]�i�H�QŪ |




































October 25th, 2007 at 10:56 am 2007�~10��25��b�W��10��56��
Hello,when I call Ext.data.Store.prototype.updateSnapshot after loading the ComboBox ,the hack had solve.�z�n�A��کI�~ext.data.store.prototype.updatesnapshot�t���ComboBox���A���J�w�ѨM�����D�C
But I click the comboBoxA again, the comboBoxB not list the data for ever.��ګ��@�Ucomboboxa�A���A comboboxb���C�X���ƾڡC
How u solve this problem? u�p��ѨM�o�Ӱ��D�H
March 7th, 2008 at 3:36 pm 2008�~3��7��b�U��3��36��
I would like to see a full source of how you are accomplishing this, unfortunately just the one snippet for me is not enough to get going.�ڷQ�ݨ�@�ӧ��㪺�ӷ��A�p���o�@�I�A�i���u�O�@�Ӥ�q�A��ڨӻ��O����������o�e���C A complete sample would definitely help here.�@�ӧ��㪺�˥��A�֩w�|���U�o�̡C