有时候我在ExtJS 6标签中遇到了奇怪的问题.我正在使用带有growMax的tagfield:3.现在当为tagfield选择的值超过三个tyhen时,我在tagfield中获得了一个指针上下选项.
这很好现在,当我点击向下箭头时,这个部分正好让我完全按照字段的底部.我无法看到其中放置了什么其他值.有什么办法可以减慢那些值的移动速度.
我的小提琴:Fiddle
重现的步骤.
它可能会跳过第二个第三个值并引导您结束.
注意:有时我需要在tagfield中为100个数据执行此操作.甚至看不出我选择的是什么和所有.我也无法改变身高.
点击滚动按钮是否有任何更激烈的事件.
解决方法
好吧,看起来你真的需要一个基于继承的解决方案.这段代码显然不是惯用的ExtJS,但似乎对我有用.首先定义一个自定义子类SingleLineTag并将’singleline-tagfield’指定为其xtype(在“旧答案”部分中有一些关于此代码背后主要思想的描述)
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(); // throttle scroll events as thy occur to often and we might scroll to much if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) { ev.preventDefault(); return; } lastScroll.lastTimeStamp = ev.timeStamp; var lstDom = me.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = me.itemList.el.dom.parentElement; var scrollTop = containerDom.scrollTop; var index = lastScroll.lastIndex; if (index >= childrenDom.length) index = childrenDom.length - 1; if (index < 0) index = 0; var lstTop = lstDom.offsetTop; if (scrollTop > lastScroll.lastTop) { // scrolling down,find next element for (; index < childrenDom.length; index++) { if (childrenDom[index].offsetTop - lstTop > scrollTop) { break; } } if (index < childrenDom.length) { // we've found the next element so change scroll position to it's top me.zzzScrollToTagIndex(index); } else { lastScroll.lastIndex = childrenDom.length; lastScroll.lastTop = containerDom.scrollTop; } } else { // scrolling up,find prev element for (; index >= 0; index--) { if (childrenDom[index].offsetTop - lstTop < scrollTop) { break; } } if (index >= 0) { // we've found the prev element so change scroll position to it's top me.zzzScrollToTagIndex(index); } else { lastScroll.lastIndex = 0; lastScroll.lastTop = 0; } } },onBeforeDeselect: function (list,record) { var me = this; me.callParent(arguments); var value = record.get(me.valueField); var index = me.getValue().indexOf(value); var lastScroll = me.zzzGetTagLastScroll(); if (lastScroll.lastIndex > index) lastScroll.lastIndex -= 1; var nextIndex = (lastScroll.lastIndex > index) ? lastScroll.lastIndex - 1 : lastScroll.lastIndex; setTimeout(function () { me.zzzScrollToTagIndex(nextIndex); },0); },onItemListClick: function(ev) { var me = this; // HACK for IE: throttle click events after scroll // click on the scrollbar seem to generate click on the "itemList" as well // which lead to showing of the dropdown var lastScroll = me.zzzGetTagLastScroll(); if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) > 200) { me.callParent(arguments); } } });
现在更改items集合中的xtype
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: [{ //xtype: 'tagfield',// old xtype: 'singleline-tagfield',// new growMax: 18,fieldLabel: 'Select a Show',store: shows,displayField: 'show',valueField: 'id',queryMode: 'local',filterPickList: true,}] });
请注意,如果您没有将此元素配置为实际只采用单行高度,则在滚动方面它会表现得很奇怪.
请参阅此Sencha fiddle的组合代码
老回答
我对ExtJS并不擅长,但我认为一些不那么好的答案总比没有答案好.首先,我同意growMax以像素为单位,因此3太少了.仍在考虑你的问题,似乎没有足够的空间来完成一个完整的滚动条,因此唯一的方法是添加自定义滚动逻辑.可能最好创建一个继承自Tag的新类,但我不确定如何在ExtJS中正确地完成它,所以这里有一些自定义的,可能是非惯用的代码.
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,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; //console.log("Scroll to " + containerDom.scrollTop); //console.log(lastScroll); } } }; var onTagScroll = function (ev) { var tagField = findComponentByElement(ev.target); var lastScroll = getTagLastScroll(tagField); // need to throttle scroll events or will scroll to much if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) { ev.preventDefault(); return; } //console.log(ev); lastScroll.lastTimeStamp = ev.timeStamp; var lstDom = tagField.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = tagField.itemList.el.dom.parentElement; var scrollTop = containerDom.scrollTop; //console.log("Before " + containerDom.scrollTop); //console.log(lastScroll); var index = lastScroll.lastIndex; if (index >= childrenDom.length) index = childrenDom.length - 1; if (index < 0) index = 0; var lstTop = lstDom.offsetTop; if (scrollTop > lastScroll.lastTop) { // scrolling down,find next element for (; index < childrenDom.length; index++) { if (childrenDom[index].offsetTop - lstTop > scrollTop) { break; } } if (index < childrenDom.length) { // we've found the next element so change scroll position to it's top scrollToTagIndex(tagField,index); } else { lastScroll.lastIndex = childrenDom.length; lastScroll.lastTop = containerDom.scrollTop; } } else { // scrolling up,find prev element for (; index >= 0; index--) { if (childrenDom[index].offsetTop - lstTop < scrollTop) { break; } } if (index >= 0) { // we've found the prev element so change scroll position to it's top scrollToTagIndex(tagField,index); } else { lastScroll.lastIndex = 0; lastScroll.lastTop = 0; } } //console.log("After " + containerDom.scrollTop); //console.log(lastScroll); }; var beforeDeselect = function (tagField,record) { var value = record.get(tagField.valueField); var index = tagField.getValue().indexOf(value); var lastScroll = getTagLastScroll(tagField); if (lastScroll.lastIndex > index) lastScroll.lastIndex -= 1; var nextIndex = (lastScroll.lastIndex > index) ? lastScroll.lastIndex - 1 : lastScroll.lastIndex; setTimeout(function () { scrollToTagIndex(tagField,nextIndex); },0); }; var attachCustomScroll = function (tagField) { var containerDom = tagField.itemList.el.dom.parentElement; containerDom.addEventListener('scroll',onTagScroll); tagField.on('beforeDeselect',beforeDeselect); };
您可以通过简单地执行类似的操作来使用它
var pnl = Ext.create('Ext.form.Panel',{ ... }); var tagField = pnl.items.items[0]; attachCustomScroll(tagField);
我的代码的主要思想是拦截包含ul所选项的容器元素的滚动事件,并将事件视为不是真正的滚动,而只是将一个元素滚动到它的方向.正常工作所需的数据以希望独特的zzzLastScroll名称附加回小部件.
还有一些逻辑可以在删除某些项目时使滚动看起来更好.
完整代码(而不是小提琴)
不幸的是,我没有ExtJS帐户,没有它我不能在那里创建一个新的小提琴,以防万一这里是我用来测试我的代码的修改后的app.js的完整代码.
var shows = Ext.create('Ext.data.Store',show: 'Star Wars: Christmas Special'} ] }); var pnl = Ext.create('Ext.form.Panel',items: [{ xtype: 'tagfield',growMax: 18,}] }); 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,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; //console.log("Scroll to " + containerDom.scrollTop); //console.log(lastScroll); } } }; var onTagScroll = function (ev) { var tagField = findComponentByElement(ev.target); var lastScroll = getTagLastScroll(tagField); if (Math.abs(lastScroll.lastTimeStamp - ev.timeStamp) < 200) { ev.preventDefault(); return; } //console.log(ev); lastScroll.lastTimeStamp = ev.timeStamp; var lstDom = tagField.itemList.el.dom; var childrenDom = lstDom.children; var containerDom = tagField.itemList.el.dom.parentElement; var scrollTop = containerDom.scrollTop; //console.log("Before " + containerDom.scrollTop); //console.log(lastScroll); var index = lastScroll.lastIndex; if (index >= childrenDom.length) index = childrenDom.length - 1; if (index < 0) index = 0; var lstTop = lstDom.offsetTop; if (scrollTop > lastScroll.lastTop) { // scrolling down,beforeDeselect); }; attachCustomScroll(window.tagField);