Flex ItemRenderer предотвращает использование переключения вкладок между вводами текста

Двойное нажатие кнопки «Отправить» довольно редко приводит к множественным вставкам, но если вы хотите получить простое решение, используйте

onsubmit="document.getElementById('submit').disabled = true"

в теге формы, если вы дадите кнопку «Отправить» id="submit"

7
задан Adam Tuttle 19 May 2009 в 19:43
поделиться

7 ответов

Я использовал mx: VBox в качестве настраиваемого itemRenderer с rendererIsEditor = "true" для моего datagrid, и я также столкнулся с проблемой порядка табуляции.

Что я понял заключается в том, что itemRenderer должен реализовать IFocusManagerComponent, чтобы FocusManager () основного приложения мог правильно перейти к нему. Я попытался реализовать этот интерфейс:

<?xml version="1.0"?>
<mx:VBox implements="mx.managers.IFocusManagerComponent" ...>
 [the rest of my itemRenderer code]
</mx:VBox>

... и оказалось довольно сложно реализовать ... множество интерфейсных функций для реализации.

Однако в моем случае мне повезло; У меня был только один элемент TextInput в моем itemRenderer (все остальное было только настраиваемым кодом, валидаторами и форматерами), поэтому я преобразовал мой itemRenderer из mx: VBox в mx: TextInput (который уже реализует IFocusManagerComponent):

<?xml version="1.0"?>
<mx:TextInput ...>
 [the rest of my itemRenderer code]
</mx:TextInput>

Вуаля! Моя проблема с порядком табуляции была исправлена.

Я полагаю, что вывод для тех из вас, у кого есть более сложные itemRenderers, заключается в том, что вам нужно либо полностью реализовать интерфейс IFocusManagerComponent в своем классе ... что, вероятно, хорошо, потому что похоже, что он расскажет flex, как настраивать вкладку через поля вашего itemRenderer. Или, возможно, вы могли бы изменить свой тег верхнего уровня на что-то, что уже реализует интерфейс, например: не могли бы вы вложить mx: VBox в что-то вроде:

<mx:Container focusIn="FocusManager.setFocus(trigger1)">

... и, возможно, он заработает? Кто-то с более сложным кодом, чем я, должен попробовать и посмотреть, что произойдет.

Или, возможно, вы могли бы изменить свой тег верхнего уровня на что-то, что уже реализует интерфейс, например: не могли бы вы вложить mx: VBox в что-то вроде:

<mx:Container focusIn="FocusManager.setFocus(trigger1)">

... и, возможно, он заработает? Кто-то с более сложным кодом, чем я, должен попробовать и посмотреть, что произойдет.

Или, возможно, вы могли бы изменить свой тег верхнего уровня на что-то, что уже реализует интерфейс, например: не могли бы вы вложить mx: VBox в что-то вроде:

<mx:Container focusIn="FocusManager.setFocus(trigger1)">

... и, возможно, он заработает? Кто-то с более сложным кодом, чем я, должен попробовать и посмотреть, что произойдет.

3
ответ дан 7 December 2019 в 10:07
поделиться

Я думаю, что могу двигаться в правильном направлении, но я еще не совсем там.

У меня есть основное приложение с HorizontalList, использующим настраиваемый ItemRenderer:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:com="ventures.view.component.*"
    layout="absolute"
    backgroundColor="#ffffff"
    preinitialize="onPreInitialize()"
    click="onClick(event)"
>
    <!-- code-behind -->
    <mx:Script source="ConsumptionChain.as" />

    <!-- show chain links -->
    <mx:HorizontalList
        id="ChainList"
        direction="horizontal"
        dataProvider="{chainData}"
        rollOverColor="#ffffff"
        selectionColor="#ffffff"
        horizontalScrollPolicy="off"
        left="20"
        right="20"
        top="20"
        height="300"
        minWidth="802"
        rowHeight="300"
        columnWidth="800"
        tabChildren="false"
        itemRenderer="ventures.view.ItemRenderer.ChainListRenderer"
    />

</mx:Application>

Я обновил образец кода в исходном вопросе, чтобы он содержал весь MXML ItemRenderer (соответствующие части); и вот код программной части ActionScript:

/*
 * ChainListRenderer.mxml.as -- code-behind for ChainListRenderer.mxml
 */

import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;

//used to combine all textboxes in a single array to make looping through them with the TAB key easier
private var allBoxes:Array;

public function expandPanel(e:Event):void {
    trace(e.currentTarget);                
    var state : String = e.currentTarget.parent.parent.id;                
    if (state != this.currentState)
        this.currentState = state;
}

private function onCreationComplete():void{
    //this function will be run on each object via the map function
    function forEach(o:Object, index:int, ar:Array):void{
        o.addEventListener(FocusEvent.FOCUS_IN, expandPanel)
        o.addEventListener(MouseEvent.CLICK, stopBubble);           //don't propagate click events (which return to base state)
        o.addEventListener(KeyboardEvent.KEY_DOWN, customTabbing);  //fix tabbing between text fields
    }

    this.addEventListener(KeyboardEvent.KEY_DOWN, customTabbing);

    //loop over textboxes and add the focusIn event listener
    tpBoxes.getChildren().map(forEach);
    lpBoxes.getChildren().map(forEach);
    apBoxes.getChildren().map(forEach);

    //create an "allBoxes" array that is used by the customTabbing function
    allBoxes = tpBoxes.getChildren();
    function forEachTabbing(o:Object, index:int, ar:Array):void {
        allBoxes.splice(allBoxes.length, 0, o);
    }
    lpBoxes.getChildren().map(forEachTabbing);
    apBoxes.getChildren().map(forEachTabbing);
}

//this function is used to prevent event bubbling
private function stopBubble(e:Event):void {
    e.stopPropagation();
}

//this function re-implements tabbing between text fields, which is broken when inside an itemRenderer
public function customTabbing(e:KeyboardEvent):void {
    trace('keyCode: ' && e.keyCode.toString());
    if (e.keyCode == flash.ui.Keyboard.TAB){
        trace(focusManager.getFocus());
        //loop over array of all text-boxes
        for (var i:int = 0; i < allBoxes.length; i++){
            trace(i.toString());
            //if event (keypress) current target is the current TextInput from the array
            if (e.currentTarget == allBoxes[i]){
                //then focus the NEXT TextInput, and wrap if at last one
                allBoxes[((i+1) % allBoxes.length)].setFocus();
                //break out of the loop
                break;
            }
        }

        //prevent arrow keys from navigating the horizontal list
        e.stopPropagation();
    }
}

По сути, я пытаюсь повторно реализовать табуляцию, проверяя наличие клавиши TAB в событии key_down каждого текстового поля и используя это для перемещения фокуса на следующий TextInput (переход к первому TextInput от последнего). Однако это не дает желаемого эффекта, и фокус все равно переходит к следующему элементу управления за пределами этого HorizontalList.

Есть идеи, что делать дальше?

0
ответ дан 7 December 2019 в 10:07
поделиться

Почему вы делаете tabChildren = "false"? Разве вы не хотите вкладывать дочерние элементы HorziontalList? поскольку itemRenderer является дочерним по отношению к списку ....

0
ответ дан 7 December 2019 в 10:07
поделиться

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

0
ответ дан 7 December 2019 в 10:07
поделиться

У меня была такая же проблема, я решил ее, попробовав переопределить поведение кнопки табуляции. Подсказкой к успеху является просто использование метода event.preventdefault(). Использованный код показан заранее.

private function initFocusMap():void {
    focusMap = {
        InNom:benefPersona.InApePat,
        InApePat:benefPersona.InApeMat,
        InApeMat:benefPersona.InFecNacimiento,
        InFecNacimiento:benefPersona.InRFC,
        InRFC:benefPersona.InCURP,
        InCURP:benefPersona.InIdSexo,
        InIdSexo:benefPersona.InIdParentesco,
        InIdParentesco:benefPersona.InPorc,
        InPorc:domBeneficiario.InCalle,
        InCalle:domBeneficiario.InNumExterior,
        InNumExterior:domBeneficiario.InNumInterior,
        InNumInterior:domBeneficiario.InCP,
        InCP:domBeneficiario.InColonia,
        InColonia:domBeneficiario.InIdPais,
        InIdPais:domBeneficiario.InIdEdo,
        InIdEdo:domBeneficiario.InIdCiudad,
        InIdCiudad:benefPersona.InNom                   
    }
}

private function kfcHandler(event:FocusEvent):void {
    var id:String = ""
    if (event.target is AperClsDateField || event.target is AperClsCombo) {
        id = event.target.id;
    } else {
        id = event.target.parent.id;
    }
    if (id != "InIdDelegacionMunic") {
        event.preventDefault();             
        focusManager.setFocus(focusMap[id]);
    }
}
0
ответ дан 7 December 2019 в 10:07
поделиться

Я столкнулся с той же проблемой с itemRender, используемым в компоненте, производном от ListBase. Я обнаружил, что все компоненты, производные от ListBase оберните все средства визуализации элементов в ListBaseContentHolder.

Из источника ListBase:

/**
 *  An internal display object that parents all of the item renderers,
 *  selection and highlighting indicators and other supporting graphics.
 *  This is roughly equivalent to the <code>contentPane</code> in the 
 *  Container class, and is used for managing scrolling.
 */
protected var listContent:ListBaseContentHolder;

Для свойств tabChildren и tabEnabled этого класса по умолчанию установлено значение false. Единственный обходной путь, который я смог найти, - это создать компонент MyList, производный от List, и переопределить метод createChildren (где listContent инициализирован) следующим образом:

import flash.display.DisplayObject;
import mx.controls.List;

public class MyList extends List {
    override protected function createChildren():void {
            super.createChildren();
            this.listContent.tabChildren = this.tabChildren
            this.listContent.tabEnabled = this.tabEnabled
        }
    }

Затем, используя "" вместо Компонент «» вернул мне функцию табуляции в ItemRender.

Надеюсь, это поможет,

3
ответ дан 7 December 2019 в 10:07
поделиться

Вот как это происходит с ComboBox itemEditor:

http://blog.flexmonkeypatches.com/2008/02/18/simple-datagrid-combobox-as-item-editor-example/

0
ответ дан 7 December 2019 в 10:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: