ExtJS 4: Utilizando a classe Ext.util.KeyMap
Autor: Weslley Alves | Publicado: 2013-03-10T18:49:00-07:00

Olá meu caro leitor(a) hoje venho trazer mais um dica sobre o ExtJS4, neste post irei demonstrar com um exemplo prático como adicionar um monitoramento para efetuar uma determinada ação ao pressionar a tecla ENTER em um Form.
Muitos que utilizavam a versão ExtJS3 ao começar a migrar suas aplicações para a versão ExtJS4 sentiram a falta do atributo keys no Form&nbsp;que lhe proporcionava adicionar os códigos das teclas que&nbsp;desejávamos&nbsp;monitorar para que possamos executar uma ação, como por exemplo, ao pressionar ENTER submeter os dados do Form.
Para que possamos realizar esse monitoramento na versão ExtJS4 devemos adicionar esse monitoramento utilizando a classe&nbsp;Ext.util.KeyMap. Também existem outras formas porém não irei abordar essas neste post. Se olharmos na API DOC iremos ver alguns exemplos de utilização desta classe, como o exemplo demonstrado abaixo:
// map one key by key code
var map = new Ext.util.KeyMap({
    target: "my-element",
    key: 13, // or Ext.EventObject.ENTER
    fn: myHandler,
    scope: myObject
});

Nesse exemplo é criado um monitoramento para a tecla ENTER cujo seu código é o valor 13. A classe Ext.EventObject contém as constantes com os valores para as teclas que podem ser monitoradas como o caso "Ext.EventObject.ENTER". Abaixo irei detalhar os atributos informados nesse exemplo:
- target: nesse atributo deve ser informado para quem deve ser monitorado o evento, ou seja, para qual componente que deve ser monitorado a devida tecla informada no atributo keys. Se olharmos na API DOC iremos ver que ele pode receber vários tipos de dados nesse atributo como o próprio componente, o ID do componente, entre outros.
- key: como já mencionado acima neste atributo deve ser informado o código da tecla que deve ser monitorada no componente. No nosso caso o ENTER.
- fn: aqui deve ser definida uma função que será chamada quando a tecla informada no atributo key for pressionada dentro do componente. Pode-se utilizar o atributo handler que não consta na API para informar o método que será executado ao pressionar a tecla.
- scope: como o próprio nome diz informa qual sera o scope de execução do método informado no atributo fn, ou seja, qual é objeto que será referenciado pelo this dentro do método.
Existem outros exemplos na API DOC que demonstram como adicionar vários monitoramentos para o mesmo componente porém para teclas diferentes. Para maiores detalhes dê uma olhada nos exemplos e na descrição de cada um para entender melhor.
Irei demonstrar no exemplo abaixo como monitorar a tecla ENTER em um Form, quando pressionado ira validar o Form e informar para o usuário os dados a serem enviados caso este Form esteja válido. Então vamos ao código:
Ext.define('ExtExample.form.Panel', {
     extend: 'Ext.form.Panel'
    ,alias: 'widget.formexample'
    ,bodyPadding: 5
    ,defaultType: 'textfield'
    ,frame: true
    ,fieldDefaults: {
         anchor: '99%'
        ,labelWidth: 70
    }
    /**
     * @cfg {Ext.util.KeyMap} keyMap
     * Objeto do mapeamento da tecla ENTER
     */
    ,keyMap: null
    ,initComponent: function() {
        var me = this;

        me.items = [{
             name: 'nome'
            ,fieldLabel: 'Nome'
            ,allowBlank: false
        }, {
             name: 'email'
            ,fieldLabel: 'E-mail'
            ,allowBlank: false
            ,vtype: 'email'
        }];

        me.buttons = [{
             text: 'Salvar'
            ,scope: me
            ,handler: me.saveData
        }];

        me.callParent();
    }
    ,afterRender: function() {
        var me = this;

        me.callParent(arguments);

        me.keyMap = new Ext.util.KeyMap({
             target: me.getEl()
            ,key: Ext.EventObject.ENTER
            ,scope: me
            ,fn: me.saveData
        });
    }
    ,onDestroy: function() {
        var me = this;
  
        // Removendo o handler do mapeamento
        me.keyMap.destroy();

        // Eliminando a referência do mapeamento
        me.keyMap = null;

        me.callParent(arguments);
    }
    ,saveData: function() {
        var me = this,
            form = me.getForm(),
            title, msg, icon;

        if(form.isValid()) {
            title = 'Valores do Form';
            msg = Ext.encode(form.getValues());
            icon = Ext.window.MessageBox.INFO;

            // TODO: Realizar o submit do Form
        }
        else {
            title = 'Form inválido';
            msg = 'Verificar campos inválidos!';
            icon = Ext.window.MessageBox.ERROR;
        }

        Ext.Msg.show({
             title: title
            ,msg: msg
            ,icon: icon
            ,buttons: Ext.Msg.OK            
        });
    }
});

No código acima será criado uma nova classe que irá implementar o monitoramento da tecla ENTER nas linhas #43 a #48 criamos o mapeamento e armazenamos a sua referência no atributo keyMap&nbsp;que será utilizado quando a nossa classe for destruída destruindo essa referência removendo o monitoramento da tecla para esse componente.
É muito importante remover o monitoramento do evento quando o componente não existir, pois existirá um monitoramento para um componente inexistente na aplicação.
Então agora só falta criarmos uma instância dessa nova classe para verificarmos o funcionamento desse monitoramento. Veja o exemplo abaixo:

Ext.onReady(function(){
    Ext.create('ExtExample.form.Panel', {
         renderTo: Ext.getBody()
        ,title: 'Enviar dados através do ENTER'
        ,width: 350
        ,height: 120
    });
});

A imagem abaixo demonstra como ficará o nosso componente, onde terá dois campos que serão validados quando o usuário clicar no botão "Salvar" ou pressionar a tecla ENTER em um dos campos contidos neste componente.



Formulário com o monitoramento da tecla ENTER

Nesse exemplo utilizamos a classe Ext.util.KeyMap para adicionar o monitoramento da tecla ENTER em um Form porém&nbsp;poderíamos utilizar esse tipo de&nbsp;monitoramento&nbsp;em qualquer elemento/componente da nossa aplicação como o exemplo:
Ext.onReady(function () {
    var map = new Ext.util.KeyMap({
         target: Ext.getBody()
        ,key: Ext.EventObject.A
        ,ctrl: true
        ,defaultEventAction: 'stopEvent'
        ,handler: function() {
            Ext.Msg.alert('Tecla pressionada', 'A tecla "CTRL+A" foi pressionada');
        }
    });
});

Esse exemplo foi retirado do site http://ext4all.com, porém fiz algumas modificações como adicionar uma função para exibir uma mensagem quando o usuário pressionar as teclas CTRL junto com a tecla A e a definição do monitoramento. Veja que temos dois novos atributos:
- ctrl:&nbsp;que irá informar se ao pressionar a tecla informada no atributo key&nbsp;se a tecla CTRL também deve estar pressionada.
- defaultEventAction:&nbsp;informa qual será a ação padrão que deverá ser executada após o monitoramento da tecla ser feito. Para maiores detalhes de quais ações são suportadas dê uma olhada no atributo defaultEventAction na API DOC.

Espero que tenham gostado de mais essa dica. Agradeço pela leitura e até o próximo post.

 SyntaxHighlighter.highlight();