Passo-a-passo: criando extensão para tela de login

Passo-a-passo: criando extensão para tela de login

Toda aplicação inicia-se por uma tela de autenticação. Partindo desse pressuposto que escrevo esse post, que ensina tanto como criar uma tela de login, como também criar uma extensão. Para essa extensão segui uma lógica um pouco diferente: imaginei como eu queria que fosse o produto final e então desenvolvi tendo esse modelo como meta. Anunciei no twitter que faria uma tela de login configurável em quatro linhas mas acabei com uma configuração de uma linha somente! O produto final que imagine foi:

new Ext.ux.LoginWindow({ url: 'login.ajax.php' }).show();

Só isso e mais nada! Toda validação, mostrar mensagens, gerenciar layout da janela, tudo está pré-configurado. Ultimamente tenho estudado um pouco de ruby on rails (linguagem/framework fantásticos) e um dos conceitos chave é “Convenção sobre configuração”. Foi algo que tentei implementar nessa extensão. Não se assuste, a nossa interface vai ter uma grande abertura para personalizações, mas se você não quiser a tela ainda assim vai funcionar 100%! :D

Preparando terreno

Como todos os outros tutoriais, me beneficio da estrutura da pasta examples do ext. Nela vamos criar um sub-diretório loginWindow.

ext-folder-loginwindow

Esse tutorial aborda somente a criação do plugin, então os arquivos PHP e as imagens que usaremos você pode obter no pacote completo disponível no final do fonte. Sugiro extrair somente esses recursos, deixe para criar a extensão você mesmo com a ajuda passo-a-passo desse tutorial. Ver o código final vai tirar um pouco a graça da coisa (:

Ext.ux.LoginWindow

Dentro da pasta Ext.ux.LogWindow crie o arquivo .js e .css correspondentes com a imagem anterior. O primeiro passo de uma extensão é criar sua estrutura básica decidindo a que classe ela vai estender. Nesse caso, iremos estender de Ext.Window

Ext.ux.LoginWindow = Ext.extend(Ext.Window,{ /* aqui vai todo o codigo */ });

Em seguida, vamos começar a pré-configurar essa janela, adicionando título, dimensões, e demais propriedades

Ext.ux.LoginWindow = Ext.extend(Ext.Window,{

//Config Options {
iconCls : 'ico-cadeado'
,layout : 'form'
,bodyStyle : 'padding:10px;'
,title : 'Autenticação'
,labelAlign : 'right'
,closable : false
,constrain : true
,width : 300
,height : 140
,labelWidth : 45
,minHeight : 140
,minWidth : 220

//}

});

Você já pode experimentar utilizar a extensão sem problemas, apesar dela ainda não estar funcional. É uma boa prática programar e testar, programar e testar, para que caso um erro ocorra você saber facilmente qual alteração ocasionou o erro.

Agora então devemos criar os campos de login e senha, e também o botão para autenticar. Tudo isso faremos no método initComponent, o método que na cadeia dos componentes é responsável pela sua inicialização. Vamos também permitir ao programador personalizar esses campos, caso ele deseje personalizar uma label, emptyText, width, style, etc…Faremos isso criando 2 config options chamados loginField e senhaField, que irão sobrescrever as regras que definimos. Faremos ainda mais e vamos permitir que essas configurações sejam string, assumindo assim o label do campo. Se testarmos novamente poderemos ver os componentes já na tela.

//Inits {

,initComponent: function()
{
if(Ext.isString(this.loginField))
this.loginField = {fieldLabel: this.loginField};

if(Ext.isString(this.senhaField))
this.senhaField = {fieldLabel: this.senhaField};

Ext.apply(this,{
defaults:{
anchor: '-18'
}
,items : [
Ext.apply({
xtype : 'textfield'
,fieldLabel : 'Login'
,emptyText : 'Informe seu login'
,msgTarget : 'side'
,itemId : 'txtLogin'
,allowBlank : false
,selectOnFocus : true
,enableKeyEvents: true
,listeners : {
scope : this
,'keyup': this._onTxtKeyUp
}
},this.loginField)
,
Ext.apply({
xtype : 'textfield'
,inputType : 'password'
,fieldLabel : 'Senha'
,emptyText : '*fakepass*'
,msgTarget : 'side'
,itemId : 'txtSenha'
,allowBlank : false
,selectOnFocus : true
,enableKeyEvents: true
,listeners : {
scope : this
,'keyup': this._onTxtKeyUp
}
},this.senhaField)
]
,buttons: [{
xtype : 'button'
,text : 'Entrar'
,iconCls: 'ico-app-go'
,scope : this
,handler: this._onBtnEntrarClick
}]
});

Ext.ux.LoginWindow.superclass.initComponent.call(this);
}

//}

Caso o servidor não autentique o usuário iremos mostrar uma mensagem de erro ao lado do botão de autenticar. Para isso iremos manipular um pouco os elementos DOM. Criaremos ao lado do botão uma div que irá conter as mensagens de erro. Faremos uso do método onRender, sobrescrevendo-o:

//Overrides {

,onRender: function()
{
Ext.ux.LoginWindow.superclass.onRender.apply(this, arguments);

var btnCt = this.footer.child('.x-panel-btns');
this._errorCt = btnCt.insertFirst({
cls: 'error-msg'
,cn : ''
});
}

//}

Tendo feito tudo isso, basta agora criar o método que lança a requisição ao servidor e resgata sua resposta. Em complemento adiciono o listener dos campos, para que ao pressionar a tecla enter a autenticação também seja disparada. Também iremos permitir que o programador adicione mais parâmetros a requisição através do config options params.

//Listeners{

,_onTxtKeyUp: function(txt,e)
{
if(e.getKey() === e.ENTER)
{
e.stopEvent();
this._onBtnEntrarClick();
}
}

,_onBtnEntrarClick: function()
{
var txtLogin = this.getComponent('txtLogin');
var txtSenha = this.getComponent('txtSenha');

if(!txtLogin.isValid() && !txtSenha.isValid())
return false;

this.buttons[0].disable();

Ext.Ajax.request({
url : this.url
,method : 'POST'
,scope : this
,params : Ext.applyIf({
login: txtLogin.getValue()
,senha: txtSenha.getValue()
},this.params)
,success: function(response)
{
response = Ext.decode(response.responseText);

if( response.success )
{
this.el.mask();
window.location.href = response.redirect||this.redirectUrl;
}
else
{
this._errorCt.update(response.message||"Login e/ou senha inválidos");
this._errorCt.fadeIn();
txtLogin.focus();
}
}
,callback: function()
{
this.buttons[0].enable();
}
});
}

//}

Nossa extensão está pronta! A requisição é feita, e o servidor deve responder um json com a propriedade success. Caso verdadeiro, o usuário está autenticado e eu posso redirecioná-lo para url informada pelo servidor, ou uma url padrão informada pelo usuário na definição da janela. Caso falso, uma mensagem de erro, informada pelo servidor ou a padrão, irá ser mostrada ao usuário.

Conclusão

Perceba como fazemos o uso da sobrescrita de métodos para criar extensões. Se você quiser utilizar somente os componentes pré-definidos do Ext você não precisa de muito esforço, mas para extrair ao máximo sua produtividade é preciso estudar a estrutura dos componentes. Eu só sei da existência de um método onRender que pode ser sobrescrito porque um dia eu abri o código fonte de Ext.Window, Ext.Panel, Ext.Component e estudei um pouco. Portanto, não tenha medo de abrir o código fonte do Ext. Seus 500 e poucos KB assustam mas no fim ele é feito do bom e velho javascript que conhecemos bem.

Aproveito o post para anunciar uma novidade do ExtDesenv, estou adicionando a documentação Ext ao site. E mais do que isso, estou adicionando a documentação dessa extensão que acabamos de fazer no site. Além do que, está rolando um projeto para tradução da documentação para o português, quem sabe o extdesenv pode contribuir com o projeto! ;D

E é isso aí galera! Espero ter sido o mais explicativo possível. Caso tenham qualquer dúvida não hesitem em me contactar. Deixo aqui link para a documentação, exemplo on-line e código-completo. Forte abraço e até a próxima!

server-side.zip

Código Completo

Demo Online

Demo Online

documentação.zip

Documentação

P.S.: Nosso colega Wemerson Januario já havia criado uma extensão para o mesmo propósito que chamou também de Ext.ux.LoginWindow. Para visualizar sua extensão veja no seu post no fórum. Valeu pelo apoio Wemerson!

Posts relacionados:

  1. Criando Ext.Window para edição de dados de um grid – CRUD Local
  2. Carregar código Ext sob demanda
  3. Cadastro básico com grid e formulário
  4. Efeito “piscar” em Ext.TabPanel
  5. Paginação de dados com Ext
  • Comentários [16]
    • Share