Refresh (actually implement inheritance)
OK, it looks like you really need an inheritance based solution. This code is obviously not an idiomatic ExtJS, but it seems to work for me. First, define a custom subclass of SingleLineTag and assign 'singleline-tagfield' as its xtype (in the section “senior answer” there is a description of the main ideas of this code)
Ext.define('Ext.form.field.SingleLineTag', { extend: 'Ext.form.field.Tag', xtype: 'singleline-tagfield', initEvents: function () { var me = this; me.callParent(arguments); me.itemList.el.dom.parentElement.addEventListener('scroll', Ext.bind(me.zzzOnTagScroll, me)); }, zzzGetTagLastScroll: function () { var me = this; return me.zzzLastScroll = me.zzzLastScroll || { lastIndex: 0, lastTop: 0, lastTimeStamp: 0 }; }, zzzScrollToTagIndex: function (index) { var tagField = this; var lastScroll = tagField.zzzLastScroll; if (lastScroll) { var lstDom = tagField.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = tagField.itemList.el.dom.parentElement; if ((index >= 0) && (index < childrenDom.length)) { lastScroll.lastIndex = index; containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop; } } }, zzzOnTagScroll: function (ev) { var me = this; var lastScroll = me.zzzGetTagLastScroll();
Now change xtype in items collections
var shows = Ext.create('Ext.data.Store', { fields: ['id', 'show'], data: [ {id: 0, show: 'Battlestar Galactica'}, {id: 11, show: 'Doctor Who'}, {id: 2, show: 'Farscape'}, {id: 3, show: 'Firefly'}, {id: 4, show: 'Star Trek'}, {id: 5, show: 'Star Wars: Christmas Special'} ] }); Ext.create('Ext.form.Panel', { renderTo: Ext.getBody(), title: 'Sci-Fi Television', height: 200, width: 300, items: [{
Please note that if you do not adjust this element to the actual length of only one row of height, it will behave strangely in terms of scrolling.
See the combined code in the Sencha violin
Old answer
I am not very good at ExtJS, but I think that not a good answer is better than no answer at all. First of all, I agree that growMax is in pixels and therefore 3 is too small. Still considering your problem, it seems that there is not enough space for a full-scale scrollbar, so the only way is to add custom scroll logic. It's probably best to create some new class that inherits from Tag , but I'm not sure how to do it correctly in ExtJS, so here is some kind of custom and probably non-idiomatic code.
function findComponentByElement(node) { var topmost = document.body, target = node, cmp; while (target && target.nodeType === 1 && target !== topmost) { cmp = Ext.getCmp(target.id); if (cmp) { return cmp; } target = target.parentNode; } return null; } var getTagLastScroll = function (tagField) { return tagField.zzzLastScroll = tagField.zzzLastScroll || { lastIndex: 0, lastTop: 0, lastTimeStamp: 0 }; }; var scrollToTagIndex = function (tagField, index) { var lastScroll = tagField.zzzLastScroll; if (lastScroll) { var lstDom = tagField.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = tagField.itemList.el.dom.parentElement; if ((index >= 0) && (index < childrenDom.length)) { lastScroll.lastIndex = index; containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop;
You can use it just by doing something like
var pnl = Ext.create('Ext.form.Panel', { ... }); var tagField = pnl.items.items[0]; attachCustomScroll(tagField);
The main idea of ​​my code is to intercept the scroll event for a container element containing ul with the selected elements and handle the events not as real scrolling, but as a direction for scrolling through one element to it. The data necessary for proper operation is attached back to the widget, apparently by the unique name zzzLastScroll .
There is also an additional piece of logic to make scrolling better when some element is removed.
Full code (instead of violin)
Unfortunately, I don’t have an ExtJS account, and without it I can’t create a new script there, so just in case there will be the full code of the modified app.js , which I used to check my code.
var shows = Ext.create('Ext.data.Store', { fields: ['id', 'show'], data: [ {id: 0, show: 'Battlestar Galactica'}, {id: 11, show: 'Doctor Who'}, {id: 2, show: 'Farscape'}, {id: 3, show: 'Firefly'}, {id: 4, show: 'Star Trek'}, {id: 5, show: 'Star Wars: Christmas Special'} ] }); var pnl = Ext.create('Ext.form.Panel', { renderTo: Ext.getBody(), title: 'Sci-Fi Television', height: 200, width: 300, items: [{ xtype: 'tagfield', growMax: 18, fieldLabel: 'Select a Show', store: shows, displayField: 'show', valueField: 'id', queryMode: 'local', filterPickList: true, }] }); window.tagField = pnl.items.items[0]; window.lstDom = window.tagField.itemList.el.dom; window.container = window.lstDom.parentElement; tagField.setValue([11, 3, 4, 5]); function findComponentByElement(node) { var topmost = document.body, target = node, cmp; while (target && target.nodeType === 1 && target !== topmost) { cmp = Ext.getCmp(target.id); if (cmp) { return cmp; } target = target.parentNode; } return null; } var getTagLastScroll = function (tagField) { return tagField.zzzLastScroll = tagField.zzzLastScroll || { lastIndex: 0, lastTop: 0, lastTimeStamp: 0 }; }; var scrollToTagIndex = function (tagField, index) { var lastScroll = tagField.zzzLastScroll; if (lastScroll) { var lstDom = tagField.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = tagField.itemList.el.dom.parentElement; if ((index >= 0) && (index < childrenDom.length)) { lastScroll.lastIndex = index; containerDom.scrollTop = lastScroll.lastTop = childrenDom[index].offsetTop - lstDom.offsetTop;