24 fev 2011

Two-way Data Binding – Flex 4

Two-way data binding é uma das novidades do flex 4 e para quem não conhece, vou mostrar como funciona e o que mudou em relação ao Flex 3.

No Flex 3 tinhamos data binding de apenas uma via, como mostra o exemplo abaixo:

1
2
<mx:TextInput id="tiValor1"/>
<mx:TextInput id="tiValor2" text="{tiValor1.text}"/>

Nesse exemplo, caso o valor da caixa de texto do tiValor1 mudasse, o valor da caixa de texto do tiValor2 seria alterado também, porém, se o valor da caixa tiValor2 fosse alterado, nada seria refletido a caixa de texto tiValor1.

No Flex 4 temos data binding de duas vias, como mostra o exemplo:

1
2
<s:TextInput id="tiValor1"/>
<s:TextInput id="tiValor2" text="@{tiValor1.text}"/>

Nesse exemplo notamos que a anotação “@” foi colocada antes do meu código “{tiValor1.text}”, essa anotação identifica um data binding de duas vias. O resultado desse exemplo é: Caso eu altere o texto da caixa de texto tiValor1, ele será refletido na caixa de texto tiValor2, e vice-versa.

Obviamente esse exemplo da funcionalidade é muito básico e serve apenas para demonstrar a funcionalidade, logo vou apresentar uma situação real que acontece a todo momento em qualquer aplicação.

Para o nosso exemplo real, vou utilizar uma situação comum para qualquer tipo de aplicação, o CRUD. Para todo CRUD precisamos sempre fazer essas 3 operações:
1. Mostrar o objeto carregado do back-end nas caixas de texto. (Famoso método carregaObjeto)
2. Atualizar o objeto com os novos valores das caixas de texto. (Famoso método preencherObjeto)
3. Limpar as caixas de textos. (Famoso método limpar)

No flex 3 teriamos o seguinte cenário.
Para a situação 1:
caixaDeTexto.text = Objeto.valor;
Para a situação 2:
Objeto.valor = caixaDeTexto.text;
Para a situação 3:
caixaDeTexto.text = “”;

Para quem usava o data binding do flex 3 de uma forma correta, conseguia resolver uma das situações com ele, mas nas outras situações sempre acabava escrevendo a linha de código apresentada.

No flex 4 poderiamos resolver da seguinte forma:

1
<s:TextInput id="caixaDeTexto" text="@{Objeto.valor}"/>

Com essa simples mudança, nós evitaríamos todas as situações acima, dispensando os métodos de carregarObjeto, preencherObjeto e limpar objeto.

Veja o exemplo funcional abaixo:
[kml_flashembed movie=”http://www.redspark.io/wp-content/uploads/TwoWayBind.swf” width=”600″ height=”450″ fversion=”10″/]

Fonte:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
               xmlns:s="library://ns.adobe.com/flex/spark" maxHeight="400" maxWidth="600"
               xmlns:mx="library://ns.adobe.com/flex/mx" width="600" height="400" xmlns:local="*">
    <fx:Declarations>
        <local:User id="user">
            <local:id>1</local:id>
            <local:nome>Bruno Sales</local:nome>
            <local:cidade>São Paulo</local:cidade>
        </local:User>
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            private function recarregar():void
            {
                user = new User("1", "Bruno Sales", "São Paulo");
            }
        ]]>
    </fx:Script>

    <s:layout>
        <s:HorizontalLayout verticalAlign="middle" horizontalAlign="center"/>
    </s:layout>

    <s:Panel title="Form" width="250" height="180">
        <mx:Form>
            <mx:FormItem label="Id">
                <s:TextInput id="tiValor1" text="@{user.id}" maxChars="20"/>
            </mx:FormItem>
            <mx:FormItem label="Nome">
                <s:TextInput id="tiValor2" text="@{user.nome}" maxChars="20"/>
            </mx:FormItem>
            <mx:FormItem label="Cidade">
                <s:TextInput id="tiValor3" text="@{user.cidade}" maxChars="20"/>
            </mx:FormItem>
            <mx:FormItem horizontalAlign="right">
                <s:Button label="Limpar" click="user = new User()"/>
            </mx:FormItem>
        </mx:Form>
    </s:Panel>

    <s:Panel title="Objeto User" width="300" height="180">
        <s:layout>
            <s:VerticalLayout verticalAlign="middle" horizontalAlign="center"/>
        </s:layout>
        <s:Label id="label" text="{user.toString()}"/>
        <s:Button label="Recarregar Objeto" click="recarregar()"/>
    </s:Panel>

</s:Application>

Comments

  • Leonardo
    fevereiro 25, 2011 Responder

    Post muito bom, só podia falar mais sobre quando a propriedade do objeto for do tipo int ou number.

  • João Felipe – Jotaefe
    fevereiro 26, 2011 Responder

    Muito bom Bruno,

    Este novo recurso realmente é uma mão na roda hehe, gostei do exemplo que utilizou para demonstrar a utilização, parabéns.

    Abraços,

  • Bruno Ferreira
    março 1, 2011 Responder

    Bom dia Bruno,
    Primeiramente parabéns pelo post, realmente se trata de um recurso bastante útil, além de muito interessante.
    Eu gostaria de saber se existe a possibilidade de implementar o Data Binding de duas vias em declarações e/ou criações de componentes via action script.
    Para ficar mais claro veja o exemplo abaixo.

    txtAbreviacao=new TextInput();
    txtAbreviacao.maxChars=25;
    txtAbreviacao.text = ???
    frmItem.addChild(txtAbreviacao);

    O que teria de ser colocado na propriedade “text” do TextInput para que tivesse o mesmo resultado do seu exemplo?

    Grato pela atenção.

  • Bruno Sales
    março 3, 2011 Responder

    @Bruno Ferreira

    Eu tentei ver o AS que é gerado quando utilizamos two-way data binding porém ele é bem extenso e confuso, precisaria de mais tempo para enteder e extrair o necessário.
    Caso você queira ver como ele se comporta, faça o exemplo citado e compile com o argumento -keep-generated-actionscript.

  • Joel Backschat
    setembro 1, 2011 Responder

    Muito bom a DCLICK como sempre de parabéns.

Leave a Comment