Sencha Touch 2: Exemplo Página de Login
Oi Pessoal,
Recebi alguns pedidos e sugestões de post para o blog que é fazer uma página de Login com Sencha Touch 2. E aqui estou escrevendo um post sobre isso! :)
Hoje então vou mostrar passo a passo como fazer uma página bem simples de login com Sencha Touch - para caso alguém queira usar de base. Não vou falar sobre autenticação, pois senão já entra em um assunto muito amplo e que vai depender da tecnologia usada no server side. Também não vou explicar muito a fundo, pois todos os conceitos abordei nos cursos de Ext JS 4 e Sencha Touch 2, então espero que tenha um conhecimento básico de certas coisas! :)
PS.: para quem já usa o Sencha Architect 3, deixo a dica que o SA3 já vem com um template para Login. O que vou mostrar hoje é um pouco diferente! :)
Views
O projeto consiste em 3 views: a página de login, uma página principal que está vazia (e é onde seria colocado o conteúdo da app) com um botão de logout, e um Viewport que vai ter a página de login e a página principal fazendo o wrapper da app.
Página de Login
A página de Login é apenas um Form Panel com os campos de usuário e senha, conforme screenshot abaixo:
Note que nas linhas 15 - 21 também temos uma Label hidden que é para mostrar alguma mensagem de erro como usuário e senha inválidos ou algo parecido.
E nas linhas 51 - 55 temos uma função que é para setar a mensagem de erro na Label que descrevemos acima.
Ext.define('MyApp.view.Login', { extend: 'Ext.form.Panel', alias: 'widget.loginform', config: { padding: '10px', styleHtmlContent: true, items: [ { xtype: 'toolbar', docked: 'top', title: 'Login' }, { xtype: 'label', hidden: true, hideAnimation: 'fadeOut', html: 'Por favor, entre com as credenciais corretas', itemId: 'failmsg', showAnimation: 'fadeIn', style: 'color: #990000; margin:5px 0px;' }, { xtype: 'fieldset', title: 'Login', items: [ { xtype: 'textfield', itemId: 'user', required: true, placeHolder: 'usuário' }, { xtype: 'passwordfield', itemId: 'pass', required: true, placeHolder: 'senha' } ] }, { xtype: 'button', itemId: 'loginbtn', padding: '10px', ui: 'action-round', text: 'Entrar' } ] }, showSignInFailedMessage: function(message) { var label = this.down('#failmsg'); label.setHtml(message); label.show(); } });
Página Principal
A página Principal está vazia, mas seria aqui que colocaríamos o conteúdo da app. A página consiste de um Panel com uma Toolbar que contém um botão de Logout.
E apenas para não fica vazia, deixei um HTML bem basicão só para dizer que o usuário está logado! :)
A Página Principal fica assim:
E o código:
Ext.define('MyApp.view.Main', { extend: 'Ext.Panel', alias: 'widget.mainpanel', config: { html: 'Você está logado!', styleHtmlContent: true, items: [ { xtype: 'toolbar', docked: 'top', title: 'Minha App', layout: { pack: 'end', type: 'hbox' }, items: [ { xtype: 'button', itemId: 'logoutbtn', text: 'Logout' } ] } ] } });
Viewport
O Viewport é apenas um container que irá juntar as duas views que já criamos e será o reponsável pela navegação da app. Para isso, vou usar o Card Layout, assim apenas uma view fica visível por vez.
No Card Layout, a primeira view é a view ativa por padrão, então quando o usuário carregar a app, a página de login será a view exibida e a view Main ficará escondida (só para o exemplo viu, isso não é coisa que se deva fazer em app que vai para produção :) ).
Ext.define('MyApp.view.MyViewport', { extend: 'Ext.Container', alias: 'widget.myviewport', requires: [ 'MyApp.view.Login', 'MyApp.view.Main' ], config: { layout: { type: 'card' }, items: [ { xtype: 'loginform' }, { xtype: 'mainpanel' } ] } });
Controller
Ah, o Controller é aquele cara que vai ficar escutando os eventos disparados pelos componentes (views). Para esse exemplo estamos interessados em escutar dois eventos: quando o usuário fazer um tap no botão de Login ou quando fazer um tap no botão de logout (lembrando que o tap seria o click de apps desktop).
Código:
Ext.define('MyApp.controller.Login', { extend: 'Ext.app.Controller', config: { refs: { loginForm: { selector: 'loginform', xtype: 'Ext.form.Panel' }, myViewport: { selector: 'myviewport', xtype: 'Ext.Container' }, mainPanel: { selector: 'mainpanel', xtype: 'Ext.Panel' } }, control: { "loginform #loginbtn": { tap: 'onLogInButtonTap' }, "mainpanel #logoutbtn": { tap: 'onLogOutButtonTap' } } }, onLogInButtonTap: function(button, e, eOpts) { var form = button.up('loginform'), user = form.down('#user'), pass = form.down('#pass'), label = form.down('#failmsg'), me = this; label.hide(); var userName = user.getValue(), password = pass.getValue(); var task = Ext.create('Ext.util.DelayedTask', function () { label.setHtml(''); me.onSignInCommand(form, userName, password); user.setValue(''); pass.setValue(''); }); task.delay(500); }, onLogOutButtonTap: function(button, e, eOpts) { var me = this, login = me.getLoginForm(), myViewport = me.getMyViewport(); myViewport.animateActiveItem(login, {type: 'slide', direction: 'right'}); }, onSignInCommand: function(login, username, password) { var me = this; if (username.length === 0 || password.length === 0) { login.showSignInFailedMessage('Por favor, informe seu usuário e senha.'); return; } login.setMasked({ xtype: 'loadmask', message: 'Signing In...' }); if (username.length > 0 || password.length > 0) { me.signInSuccess(); } }, signInSuccess: function() { var me = this, login = me.getLoginForm(), mainPanel = me.getMainPanel(), myViewport = me.getMyViewport(); login.setMasked(false); myViewport.animateActiveItem(mainPanel, {type: 'slide', direction: 'left'}); } });
Vamos lá!
Linhas 5 - 17 : temos as refs, que são apelidos criados para nos ajudar a referenciar esses componentes no nosso código. Essas refs são similar a usar Ext.ComponentQuery.query('selector')[0]. Por isso precisamos ter certeza de ter apenas 1 instância desses componentes no nosso código. Como selector usei o próprio alias de cada view.
Linhas 21 - 27 : aqui estamos escutando os eventos tap dos botões login e logout. Usei o itemId dos botões e para diminuir o escopo de busca do Sencha Touch, declarei também o componente (xtype/alias) que contém esses botões.
Linhas 30 - 50 : essa é a função que é executada quando o usuário faz um tap no botão Login. A idéia geral é verificar se o usuário e senha foram digitados pelo usuário (não estão vazios - pelo menos 1 char).
- Linha 31 - obter a referência do Form
- Linha 32 - com a referência do Form, pegamos a referência do campo Usuário
- Linha 33 - com a referência do Form, pegamos a referência do campo Senha
- Linha 34 - com a referência do Form, pegamos a referência da label para caso exista necessidade de exibir uma mensagem de erro
- Linha 37 - escondemos da Label de erro - caso já tenha acontecido um erro em outra ocasião
- Linhas 39 e 40 - obtemos o valor inputado de usuário e senha
- Linhas 42 - apenas para fazer um charme, na hora de fazer o login temos um pequeno delay
- Linha 49 - instanciamos o delay
- Linhas 43, 45 e 46 - limpamos os campos de usuário e senha, e a label de erro
- Linha 44 - chamada da função onSignInCommand passando o Form, e campos de usuário e senha como parâmetros
Linhas 60 - 76 : função que apenas valida se usuário e senha são válidos. Não estou fazendo nenhum verificação com o server, mas seria aqui que enviaria para o server para verificar as credenciais.
- Linha 63 a 66: se usuário e senha estão em branco, atualizados a mensagem de erro e mostramos na tela e também saímos da função terminando a execução.
- Linhas 68 a 71 - apenas uma graça mascarando a tela de login
- Linhas 73 a 75 - Se usuário e senha não estão vazios, faz o login chamando a função signInSuccess
Linhas 78 - 86 : apenas troca a view ativa do Viewport pela View Main.
- Linha 80 - obtém a referência do Form (poderíamos ter passado como parâmetro através da função anterior também)
- Linha 81 - obtém a referência da View da página principal
- Linha 82 - obtém a referência do Viewport
- Linha 84 - remove a máscara que adicionamos nas linhas 68 a 71
- Linha 85 - apenas troca a view ativa do ViewPort para a view principal fazendo uma animação para ficar bonitinho! :)
Linhas 52 - 58 : função que faz logout. Apenas coloca a view Login como view ativa do Viewport.
Download Código
O código está disponível no github: https://github.com/loiane/sencha-touch2-examples-architect/tree/master/SenchaTouchLogin
Até a próxima! :)