自定义 Flex ComboBox,根据用户输入过滤数据提供者

发布于 2024-11-08 18:07:40 字数 1764 浏览 0 评论 0原文

我有一个 ComboBox,数据提供者是一个包含 3 个值的 ArrayCollection:CA - 加利福尼亚州、NY - 纽约州、TX - 德克萨斯州。使用默认行为,当我开始在组合框中键入内容时,它将尝试匹配字符串开头的值,因此,如果我开始键入 TX,它将显示 TX - Texas。

我希望能够在字符串的任何部分进行搜索,而不仅仅是从头开始,因此如果我输入“xas”,它将过滤掉选择并仅显示 TX - 德克萨斯州。 Adobe 论坛此处中有一篇非常有用的帖子,介绍如何通过更改过滤器函数来执行此操作在为 ComboBox 提供数据的 ArrayCollection 上,我已经对其进行了调整,但我遇到了一个小问题。

如果用户选择一个值,然后尝试输入新文本,则在组合框中键入的第一个字母不会显示。

1) 在组合框中选择值 CA - California
2) 突出显示文本并按键盘上的“n”
3) 您希望看到文本框填充了“n”,但文本框仍然为空

是什么原因导致此问题?仅当您已经选择了一个值时才会发生这种情况。如果您从空白的 ComboBox 开始,它会按预期工作。

<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.events.FlexEvent;

        import spark.events.TextOperationEvent;

        [Bindable]
        public var arrC:ArrayCollection = new ArrayCollection([{label:'CA - California'},{label:'NY - New York'},{label:'TX - Texas'}]);

        private function changeHandler(e:*):void
        {
            if (arrC.filterFunction != doFilter)
                arrC.filterFunction = doFilter;
            arrC.refresh();
        }

        private function doFilter(item:Object):Boolean
        {
            if(String(item.label).toLowerCase().indexOf(cb.textInput.text.slice(0 ,cb.textInput.selectionAnchorPosition).toLowerCase())>-1)             
            {
                return true;
            }
            return false;
        }                       

        protected function application1_creationCompleteHandler(event:FlexEvent):void
        {
            cb.textInput.addEventListener(TextOperationEvent.CHANGE,changeHandler );
        }

    ]]>
</fx:Script>

<s:ComboBox id="cb" dataProvider="{arrC}"/>

I have a ComboBox and the data provider is an ArrayCollection of 3 values: CA - California, NY - New York, TX - Texas. With the default behavior when I start typing in the ComboBox it will try to match the value from the beginning of the string, so if I start Typing TX it will bring up TX - Texas.

I want to be able to search at any part of the string and not just from the beginning, so if I type "xas" it will filter out the selection and only show TX - Texas. There is a very helpful post in the Adobe forums here on how to do this by changing the filter function on the ArrayCollection which provides data for the ComboBox and I have adapted it but I am having a slight issue with it.

If a user selects a value and then tries to enter in new text the first letter typed in the ComboBox does not show up.

1) Select the value CA - California in the ComboBox
2) Highlight the text and hit "n" on your keyboard
3) You would expect to see the textbox populated with "n" but the textbox remains empty

What could be causing this issue? It only happens if you already have a value selected. If you start with a blank ComboBox it works as expected.

<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.events.FlexEvent;

        import spark.events.TextOperationEvent;

        [Bindable]
        public var arrC:ArrayCollection = new ArrayCollection([{label:'CA - California'},{label:'NY - New York'},{label:'TX - Texas'}]);

        private function changeHandler(e:*):void
        {
            if (arrC.filterFunction != doFilter)
                arrC.filterFunction = doFilter;
            arrC.refresh();
        }

        private function doFilter(item:Object):Boolean
        {
            if(String(item.label).toLowerCase().indexOf(cb.textInput.text.slice(0 ,cb.textInput.selectionAnchorPosition).toLowerCase())>-1)             
            {
                return true;
            }
            return false;
        }                       

        protected function application1_creationCompleteHandler(event:FlexEvent):void
        {
            cb.textInput.addEventListener(TextOperationEvent.CHANGE,changeHandler );
        }

    ]]>
</fx:Script>

<s:ComboBox id="cb" dataProvider="{arrC}"/>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

素手挽清风 2024-11-15 18:07:40

找到了解决您问题的方法(因为我必须制定一个行为类似于谷歌搜索输入框的自定义组件)。似乎正常的输入处理通过过滤数据提供者而陷入错误的方式。然而,我没有根据需要深入研究意外行为的根源,以提供对引起问题的可靠解释(可能的解决方案的想法来得太快了;.))。这里是:

<?xml version="1.0" encoding="utf-8"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx"
        skinClass="CGoogleComboSkin">
<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.collections.IList;

        import spark.events.TextOperationEvent;

        private var unfilteredDataProvider : IList;
        override public function set dataProvider(value:IList):void {
            super.dataProvider = value;

            unfilteredDataProvider = value;
        }

        override protected function textInput_changeHandler(
                event:TextOperationEvent):void {
            super.textInput_changeHandler(event);

            if (unfilteredDataProvider is ArrayCollection) {
                ArrayCollection(unfilteredDataProvider).filterFunction = filterMatches;
                ArrayCollection(unfilteredDataProvider).refresh();

                super.dataProvider = new ArrayCollection(unfilteredDataProvider.toArray()); 
            }
        }

        protected function filterMatches(item:Object):Boolean {
            if (item is String) {
                if(String(item).toLowerCase().indexOf(
                    textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }
            else if (labelField && labelField!= "") {
                if(item.hasOwnProperty(labelField) && 
                        String(item[labelField]).toLowerCase().indexOf(
                        textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }

            return false;
        }
    ]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>

该解决方案背后的想法是通过继承构建自定义组合框并覆盖数据提供者的设置器,以使未过滤的数据提供者作为任何文本操作未更改的源,但让弹性组合框以其通常的方式处理没有过滤器的集合附加到(任何输入都已经是源集合过滤的结果)。这只是一次尝试,但很有效,而且应用速度与我赞赏的一样快;.)

快乐的编码

Got a solution for your problem (because I had to work out a custom component behaving similar to the googles search input box). Seems the normal input processing gets into wrong ways by filtering the dataprovider. However I didnt examined the sources of the unexpected behaviour as deeply as needed to provide a solide explanation of the causing problem (the idea of a possible solution came too fast ;.)). Here it is:

<?xml version="1.0" encoding="utf-8"?>
<s:ComboBox xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx"
        skinClass="CGoogleComboSkin">
<fx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;
        import mx.collections.IList;

        import spark.events.TextOperationEvent;

        private var unfilteredDataProvider : IList;
        override public function set dataProvider(value:IList):void {
            super.dataProvider = value;

            unfilteredDataProvider = value;
        }

        override protected function textInput_changeHandler(
                event:TextOperationEvent):void {
            super.textInput_changeHandler(event);

            if (unfilteredDataProvider is ArrayCollection) {
                ArrayCollection(unfilteredDataProvider).filterFunction = filterMatches;
                ArrayCollection(unfilteredDataProvider).refresh();

                super.dataProvider = new ArrayCollection(unfilteredDataProvider.toArray()); 
            }
        }

        protected function filterMatches(item:Object):Boolean {
            if (item is String) {
                if(String(item).toLowerCase().indexOf(
                    textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }
            else if (labelField && labelField!= "") {
                if(item.hasOwnProperty(labelField) && 
                        String(item[labelField]).toLowerCase().indexOf(
                        textInput.text.slice(0,
                        textInput.selectionAnchorPosition).toLowerCase())>-1)
                    return true;
            }

            return false;
        }
    ]]>
</fx:Script>
<fx:Declarations>
</fx:Declarations>

The idea behind this solution was to construct the custom Combobox by inheritance and overriding the setter of the dataprovider in a way to have the unfiltered dataprovider as unchanged source by any textoperation but let the flex combobox deal in its usual way with a collection where no filter is attached to (which is by any input allready the result of the filtering of the source collection). It was just a try but worked and was as fast applicable as I appreciated it ;.)

happy coding

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文