14 abr 2009

Como fazer Binding em Functions corretamente?

Pode parecer uma coisa boba, mas muita gente ainda tem dúvidas de como fazer o bind em functions no Flex. O maior problema com isso é que, como o resultado de uma function pode depender de muitos fatores, o Flex não tem como saber se o valor foi atualizado ou não, portanto o bind não funciona.

Considere um exemplo bobo onde temos dois TextInput e o segundo tem um bind para uma function que multiplica o valor do primeiro por 3 sempre. Algumas pessoas tentariam fazer dessa maneira:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<mx:Script>
    <![CDATA[

        [Bindable]
        private function getNewValue():Number
        {
            return Number( tiValor1.text ) * 3;
        }

    ]]>
</mx:Script>

<mx:TextInput id="tiValor1" restrict="0-9" />
<mx:TextInput id="tiValor2" restrict="0-9" text="{getNewValue()}" />

Dessa maneira, o valor nunca será atualizado, pois o Flex não tem como saber que o “tiValor1.text” lá dentro da function deverá ser monitorado. Uma das soluções possíveis, e mais utilizadas pela maioria das pessoas, é passar uma propriedade que seja bindable como parâmetro para a function. Assim, toda vez que o valor bindable for atualizado a function será chamada novamente. Dessa maneira:

1
2
3
4
5
6
7
8
9
10
11
12
13
<mx:Script>
    <![CDATA[

        private function getNewValue ( valor:String ):Number
        {
            return Number( valor ) * 3;
        }

    ]]>
</mx:Script>

<mx:TextInput id="tiValor1" restrict="0-9" />
<mx:TextInput id="tiValor2" restrict="0-9" text="{getNewValue ( tiValor1.text )}" />

Dessa maneira, o bind com a function irá funcionar perfeitamente, mesmo sem utilizar a metadata tag [Bindable]. Mas e em casos no qual não temos como passar um valor bindable como parâmetro para a function? Um outro exemplo bobo seria de que o segundo TextInput deveria receber um valor aleatório sempre que o do primeiro TextInput fosse atualizado. Você passaria uma propriedade bindable pra function, mesmo que ele não fosse utilizada dentro da function?

Bom, lendo a documentação do Flex, você poderá encontrar uma outra solução que poucos programadores costumam utilizar. Metadata tag [Bindable] em conjunto com um evento declarado no Bindable. Nesse caso, você dispararia esse evento toda vez que desejasse que os lugares que fazem bind com a function atualizem seus valores. Exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<mx:Script>
    <![CDATA[

        [Bindable(name="valueChanged")]
        private function getNewValue():Number
        {
            return Math.random();
        }

        private function valueChanged( event:Event ):void
        {
            dispatchEvent(new Event( "valueChanged" ));
        }

    ]]>
</mx:Script>

<mx:TextInput id="tiValor1" restrict="0-9" change="valueChanged(event)" />
<mx:TextInput id="tiValor2" restrict="0-9" text="{getNewValue()}" />

Dessa maneira o bind também irá funcionar e atualizará o valor do segundo TextInput corretamente, sem a necessidade de uma “gambiarra” passando uma propriedade bindable inútil como parâmetro.

Comments

  • Beck Novaes
    abril 18, 2009 Responder

    “Thare are no dumb questions” é uma seção dos livros da série Head First. Da mesma forma eu diria “there are no dumb posts”. Não há nada de bobo nas suas dicas Gil. De fato, o Binding é muito pouco explorado no Flex. Quantos programadores Flex sabem dizer porque o Cairngorm não implementa o Observer assim como o PureMVC uma vez que este Pattern é essencial para a microarquitetura MVC ?

  • Mario Junior
    abril 22, 2009 Responder

    R: Algo me diz q o ModelLocator é um dos gargalos nessa história 🙂

  • Beck Novaes
    abril 22, 2009 Responder

    Sim o ModelLocator é um gargalo. E o Cairngorm, como todos os “Frameworks” também tem seus defeitos.

    Mas uma coisa que me incomoda é ver as pessoas modificando tanto o Cairngorm para resolver os problemas do Cairngorm que elas acabam por infringir justamente os princípios que o Cairngorm procura seguir. Ou seja,
    elas modificam tanto o Cairngorm que o MVC vai pro saco! Então eu me pergunto, para que usar o Cairngorm nestes casos? Apenas para manter um padrão de codificação, embora os Patterns estejam aplicados erroneamente?

  • Marcelo
    julho 27, 2009 Responder

    Estou em flex a pouquíssimo tempo, pra ser mais exato ainda estudo a tecnologia pra montar um protótipo integrado com Java.
    Independente do MVC entendi que funções escritas dessa maneira seriam no máximo máscaras utilizadas na interface, correto?
    Caso contrario seria responsabilidade da controler (que se julgar necessario perguntara ao model o que fazer) atualizar os valores da interface.
    Aproveitando o gancho, existe alguma biblioteca específica de máscaras no flex? Validadores? Conversores?
    Sou extremamente novo em flex, ainda nem consegui integra-lo com java direito hehe, perdoem-me pelas “dumb questions”.

    ps: Beck, sou muito grato aos seus posts, são um oasis no deserto que o google me retorna: um monte de linhas de codigo colados em blogs que chamam de tutoriais…

Leave a Comment