Chat Ext JS com Comet

Today Frozen Mountain announced the new version of their product WebSync. It allows you to create comet apps, which make the server respond requisitions instantaneous.

The performance is great! It’s hard to imagine that they could make IIS handle thousands of requisitions with their product. The demos and results are on their website, so you can be sure of it.

Take a look at the Ext JS Stock Ticker, and the Ext JS Instantaneous Chat.

Congrats to Jerod and all Frozen Mountain Team!!!

See all demos

Enjoy!

Cadastro básico com grid e formulário

Yesterday I was asked about a demo that demonstrated a basic registration screen with the list of records in one side and the form registration on the other. As said, it’s a simple interface for entries, where you view the records written in a list, and clicking on any record their data is loaded in the form. Once changed, the data are submit, and the grid is reloaded. The Ex has this example, but what differs is that my uses object oriented code and has the option to save the data.

Base Class

Will be neither a form that will contain a grid or a grid containing a form. It will be a panel with two items inside. This panel arrange the layout and also will conduct the business rule that exists between the grid and form.

GridForm = Ext.extend(Ext.Panel,{
	
	//Config Options {
	
		 title			: 'Usuários'
		,iconCls		: 'silk-user'
		,layout			: 'hbox'
		,layoutConfig	: {align: 'stretch'}
		
	//}
	
	//Inits {
	
		,initComponent: function()
		{
			//..aqui será criado o grid e o form 
			
			GridForm.superclass.initComponent.call(this);
		}
		
		,initEvents: function()
		{
			GridForm.superclass.initEvents.call(this);
			
			//aqui definiremos alguns eventos
		}
		
	//}
	
	//Listeners {
	//}
	
});

Ext.reg('bt-gridform',GridForm);

Grid

Not many secrets here. Just set the datastore, columns, and some optional settings. Interestingly, the datastore declares three fields – id, name and login – and grid declares only two columns – name and login. The ID field will be hidden but available even though I have no column for it.

this._grid = new Ext.grid.GridPanel({
	 flex		: 1
	,bodyStyle	: 'border-width:0 1px 0 0;'
	,viewConfig	: {forceFit:true}
	,store		: new Ext.data.JsonStore({
		 autoLoad	: true
		,autoDestroy: true
		,proxy		: new Ext.data.HttpProxy({url: 'usuarios.json', method: 'GET'})
		,fields		: [
			 {name:'id'		, type:'int'	}
			,{name:'nome'	, type:'string'	}
			,{name:'login'	, type:'string'	}
		]
	})
	,columns: [{
		 header		: 'Nome'
		,dataIndex	: 'nome'
	},{
		 header		: 'Login'
		,dataIndex	: 'login'
	}]
});

Form

Also not many secrets here. For the id to be passed to the server on submit I chose to create a hidden field. Also important to note the existence of the password field. Is not it interesting to show the password in the grid, but at submission time this is a important information for my user registration.

this._form = new Ext.form.FormPanel({
	 defaultType: 'textfield'
	,labelAlign	: 'top'
	,padding	: '10'
	,width		: 300
	,border		: false
	,defaults	: {anchor: '-10'}
	,items		: [{
		 xtype	: 'hidden'
		,name	: 'id'
	},{
		 fieldLabel	: 'Nome'
		,name		: 'nome'
		,allowBlank	: false
	},{
		 fieldLabel	: 'Login'
		,name		: 'login' 
		,allowBlank	: false 
	},{
		 fieldLabel	: 'Senha'
		,inputType	: 'password'
		,name		: 'senha'
	}]
	,buttons:[{
		 text	: 'Salvar'
		,scope	: this
		,handler: this._onBtnSalvarClick					 
	},{
		 text	: 'Alterar'
		,hidden	: true
		,scope	: this
		,handler: this._onBtnSalvarClick
	},{
		 text	: 'Limpar'
		,scope	: this
		,handler: this._onBtnLimparClick
	}]
});

Loading grid on row click

First we attach a listener to the event “click on a line” on the grid. Then we used the method loadRecord of Ext.form.BasicForm (all Ext.form.FormPanel has a BasicForm in it) to load the data

,initEvents: function()
{
	GridForm.superclass.initEvents.call(this);
	
	this._grid.getSelectionModel().on('rowselect',this._onGridRowSelect,this);
}

//...

,_onGridRowSelect: function(selectionModel, rowIndex, record ) 
{
	var form = this._form.getForm(); 
	
	form.loadRecord(record);
	form.findField('nome').focus(false,true);
	
	this._form.buttons[0].hide(); //salvar
	this._form.buttons[1].show(); //alterar
}

Submit the form and reload the grid

When you click Save / Update I submit the form, displaying a message while the process is not finished. When finalized (the server returns success: true) we can clear the form and reload the grid.

,_onBtnSalvarClick: function()
{
	var form = this._form.getForm(); 
	
	if(!form.isValid()){
		return false;
	}
	
	form.submit({
		 url		: 'usuariosubmit.json' //do nothing
		,waitTitle	: 'Aguarde'
		,waitMsg	: "Enviando dados..."
		,scope		: this
		,success	: function()
		{
			this._onBtnLimparClick();
			this._grid.store.reload();
		}	
	});
}

Resume

And our basic registration is ready. You just have to do all the coding for server data to be persisted. Here are the links to the full code and online demo. Ps: I didn’t code the persistent stuff so if you change any registry or create a new, nothing will happen.

Until next time!

server-side.zip

Full code

Demo Online

Online demo

Ext ION: rumors of a new product

Finally Ext Designer has been released! Developers around the world were able, last week, to download their 14 days trial copy of the software. The videos and demos posted previously reflected well the final product, which has drag ‘n drop features, integration with data from a server, instant preview, export code and etc … The team is still working hard over the designer and we are all certain that the product will suffer good updates until the end of the year.

But the post today is not to discuss the designer, but the rumors of a possible new product from Ext JS team! Designer’s demos available last year ran on the Adobe Air platform, but what we saw in the final version was not quite in line with what we know about Air Applications. Installer was totally different, not using the default Adobe Air, and also the s.o. files were different.

I noticed, when I installed, that the .dll files were pre-named with Qt, which is a Nokia cross-platform framework. So the team had ditched Air and opted for Nokia Qt?

I thought I had closed the question, but today, watching the video of Ext JS meetup organized by Jay Garcia, I noticed what is perhaps the new Ext JS product. It’s called ION and would be an API for developing cross-platform apps (based on Qt?). My impression is that the team is aware of the tendency to create web applications that run on desktop and go into the Air/Titanium Market with their own solution.

Anyway, rumors are exciting, and can be confirmed within 1 to 2 months. Let’s wait and hope, perhaps, another great product of Ext JS.

Razões para comprar o Ext Designer

It was announced here, February 19 on ExtDesenv, the pre-sale of Ext Designer, the visual editor for Ext JS. From there began an intense discussion whether it is worth purchasing the product or not. This post is a bit of my point of view and also comments from the community about it, go ahead!

What is Ext Designer

Few know but there is an official blog post providing more information and downloadable trial version of the software. In this version you can only create the screens and make prints. You can’t save any work or export the generated code. In addition there are videos showing the use of the editor. All these features are enough to give an idea of what is the designer.

Features

Drag and drop

Do not handle code, just drag and configure the components on a more intuitive way as possible. This is very positive, since we can create interfaces much more quickly than by code. People with the slightest knowledge of Ext JS can still benefit from the option of creating prototypes, which can then be improved by an Ext programmer.

Data connection

It is possible to integrate your XML or JSON data source with Ext Designer, to see your grid and other components being populated with data. Further increases productivity and creates a clear separation between data and interface. You can have a developer involved only on the server side, creating the data sources, and another in parallel creating interfaces. At the end of the work everything is attached by Ext Designer.

Save and export code

Export object-oriented code directly into the IDE of your choice. According to Jack Slocum “the code is worthy to be considered as written by himself”, but if you don’t like it you have the option to export and modify it in an IDE. The hardest part has been done, which is the creation and configuration of components.

Screenshots

As mentioned, people with minimal knowledge of Ext can prototype screens and then take screenshots. Impress your client building an interface in front of him.

And much more like saving pre-defined components for reuse, and undo and restore feature. These resources are exciting enough, but it’s enough to do a pre-sale?

Comments from community

Follow a few questions from the community forum and the responses from Ext JS team:

Q: Will it be possible to import existing projects?
A: Not for the initial release.

Q: What are your pricing plans for updates? Do you get updates for free?
A: Initially we had thoughts of an annual fee, but decided to scrap that based on community feedback.The designer is a perpetual license. This means you buy it once without any obligations to upgrade annually.We will also be providing free updates and enhancements for the designer until we announce our next version (just like ext 2 -> ext 3).

Q: Will it be possible to add support for custom components like extensions and plugins?
A: Yes. We built the designer with community extensions and the developers that support them in mind.We will be announcing more on this in the coming months.

Q: Will there be an evaluation version of the latest release of the product? Would be nice to gen and experiment code before actually purchasing.
A: We plan on offering a trial after we release the product.The limited time, 50% off promotion is following the tradition we started with version 1.x of Ext JS.

Q:How can I convince, for example, my boss to do Ext Designer pre-sale without any assurance that it will improve productivity?
A: The pre-order is heavily geared towards our community that do not require any formal approval processes. We are working on a trial, but it won’t be available until after the pre-order sale is over.

Q: When will be the official release?
A: We’re planning doing it at end of march, next to day 21.

Q: What are the advantages using Ext Designer?
A:

Using Ext Designer as a productivity tool will save you time and improve your deliverables.

It’s not intended to replace any aspect of your existing workflow, just improve it.As an example, we envision contractors spending their time with clients more productively by building interfaces in real time. The Ext Designer will also empower end users to participate in the planning and maintenance of applications, allowing you to focus on building applications faster.

The Designer is IDE independent, as such, the code generation can output to a directory of your choosing where you and your favorite editor take over.

At the end of the day, the Designer will bring a refined experience to our community, customers, and end users.

Author’s opinion

I consider myself one of those community programmers that need formal approval to make purchases like this. However only to see the product demo, videos, and comments by the development team I am convinced (and my bosses) that this will be the tool that will improve the entire process of creating interfaces. Analysts may prototypes and save their work. When I starting working on the project it will already have the prototype attached and I can take care on improving the code both through the designer, and after giving final touches to the code with an IDE. Our licenses have been acquired, and we are excited waiting for the final release.

Congratulations team Ext JS for the great work. Releases like this only confirm the confidence by the community in your work.

1 ano de ExtDesenv: novos recursos e layout

Finally the new ExtDesenv is online! I’ve been hiding for a while investing time in reshaping the portal that is now published! This month we’re celebrating 1 year of existence, and nothing better than giving a general review. I started this project in a very simply way, with a very cheap hosting and a standard wordpress layout. Now ExtDesenv has a very good hosting from DreamHost and a personalized layout.

My greatest achievement is perhaps the inclusion of multi-language plugin, which allows me to create posts in both Portuguese and English. Adding my little knowledge in English with a little help from Google Translate I will try to meet our friends outside of Brazil, seeking a higher profile not only to ExtDesenv, as well as the Brazilian community of programmers. We have very good projects here and I’m sure we can make beneficial trade with outsiders. Please consider that I am not a native language speaker so I can make many grammatical errors that I hope you help me to correct writing to my email.

Besides this feature it is also important to comment the new posts, comments and tags navigation made with Ajax. It is possible to see the latest posts, the most popular, most recent comments, and tags from the blog.

Also, I tried a lot to search a good twitter plugin to put here on the blog. The old one show only my tweets, while this search twetts of various authors and also by subject, in case #extjs. So all you have going on in twitter about Ext and tweets of people I follow, will appear alongside.

In addition I changed the examples page. I was using a layout based on the official examples page, and decided to make my own more integrated into the blog.

And to complete, a “bookcase” with books and suggested list of interesting links, so that I can share with you good resources that I find about our Ext JS world and RIA development.

I am very pleased with the overhaul and now I have everything (almost) done I can concentrate on making articles, tutorials and resume my idea of writing courses. I hope you enjoy and appreciate the new portal, as you have been done in that 1 year of ExtDesenv life.

Sincerely

Efeito “piscar” em Ext.TabPanel

I am announcing a new extension here at ExtDesenv. We’ve developed here at Ellevo Solutions, me and Maicon Shelter, this extension that allows you to catch user attention making a tab in Ext.TabPanel blink in orange. Basically we’ve created the images and the transitions between the original image and the altered one. After 10 times being altered the image stays in orange. In case user activates the tab (click or activate event) the effect is stopped and tab returns to it’s normal state.

Enjoy! (:

server-side.zip

Full Code

Demo Online

Online Demo

Anunciando Ext JS 3.2 Beta – multi-ordenação, transições e campos compostos

Terça-feira feliz! (rs) Isso porque a equipe Ext disponibilizou o beta da sua nova versão 3.2. Foi feito muito sigilo sobre as novas implementações por isso estou muito surpreso com as novidades.

Estamos felizes de anunciar que a versão beta doExt JS 3.2 está publicamente disponível. 3.2 introduz um número excitante de novos componentes e adiciona grandes capacidades a sua aplicação já existente.

 Múltipla Ordenação

Agora é possível ter um DataStore ordenado por vários campos. Veja o exemplo do grid ordenado por múltiplas colunas!

Transições animadas em DataView

O componente para visualização de dados de um Store agora conta com poderosos recursos de transições animadas. Veja o exemplo 1 em que ao ordenar os registros eles se movimentam para seus novos lugares, e o exemplo 2 em que os itens desaparecem conforme um filtro é aplicado.

Campos compostos

Agora finalmente é possível agrupar um item de formulário ao lado do outro sem precisar fazer hacks com layout column.

new Ext.form.FormPanel({<br />
    items: [<br />
      {<br />
          xtype: 'compositefield',<br />
          fieldLabel: 'Full Name',<br />
          items: [<br />
              {xtype: 'textfield', name: 'title',     width: 40},<br />
              {xtype: 'textfield', name: 'firstName', flex : 1},<br />
              {xtype: 'textfield', name: 'lastName',  flex : 2}<br />
          ]<br />
      },<br />
      //the rest of your form goes here<br />
    ]<br />
});

E muito mais…

  • Plugins para Toolbar: ordenação de itens e drag ‘n drop com toolbar.
  • Novo tema: Acessibilidade
  • Qualidade comprovada: 180 correções e melhorias. A partir dessa nova versão a equipe está utilizando testes automatizados assegurando que o framework funcione perfeitamente a cada correção.

Ext Designer será pago. Pré-vendas já disponíveis.

É isso mesmo! Para surpresa dos membros da comunidade Ext foi anunciada a pré-venda do Ext Designer, o software para desenvolver aplicações Ext de maneira visual. Ainda não tenho mais detalhes a respeito, além das informações proveninentes do site oficial.

ext-designer-presale

Ext JS em seu início era um framework fundamentalmente livre, e as mudança em licenças geraram uma discussão gigante na comunidade, e ainda a desistência de diversos membros que a apoiavam. Em minha opinião essa é mais uma decisão que irá gerar boas discussões. Não tenho muitas informações, por isso também não tenho opinião formada. Aguardaremos os “grandes” do Ext se pronunciarem no fórum oficial. Até!

Como abrir páginas de um menu no centro de sua aplicação

Sorry, this entry is only available in Português.

Muitas aplicações se baseiam em um layout com links na esquerda e com um tabPanel ao centro. Depois de responder alguns posts no fórum brasileiro sobre como abrir itens de um menu em um tabPanel central, estou escrevendo sobre o assunto aqui no blog através de tutorial.

Primeiramente vamos criar uma subpasta abrirPaginaCentro dentro da pasta examples do Ext. Depois disso criar um arquivo index.html com o código abaixo e um arquivo abrirPaginaCentro.js, por enquanto em branco.

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
        <title>Abrindo páginas de menu no centro da aplicação - www.extdesenv.com.br</title>

		<!--css-->
        <link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css"/>
        <link rel="stylesheet" type="text/css" href="../shared/examples.css" />
        <link rel="stylesheet" type="text/css" href="../shared/icons/silk.css" />
        <style type="text/css">
            .no-icon {
                display: none;
            }
        </style>

        <!--js-->
        <script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
        <script type="text/javascript" src="../../ext-all.js"></script>
        <script type="text/javascript" src="abrirPaginaCentro.js"></script>
    </meta></head>
    <body>
    </body>
</html>

Sua configuração deve estar assim:

  • examples
    • abrirPaginaCentro
      • abrirPaginaCentro.js
      • index.html

Então agora no arquivo JS vou criar definir uma nova classe AbrirPaginaCentro:

var AbrirPaginaCentro = Ext.extend(Ext.util.Observable,{

	constructor: function(){
		//..aqui vai toda definição dos componentes...

		//super
		AbrirPaginaCentro.superclass.constructor.apply(this,arguments);
	}
});

Ext.onReady(function()
{
	new AbrirPaginaCentro();
});

Feito esse esqueleto de classe vamos em 3 passos fazer tudo funcionar:

  1. Crio os componentes: o tabPanel, o viewport para conter os itens, e o menu lateral formado de um painel accordion com treePanels. O seu menu lateral pode ser o que quiser, treePanels, labels, buttons…Não importa o componente, o que importa é que quando clicado dispare um evento.

    //tabPanel
    this.tabPanelCentral = new Ext.TabPanel({
        region		: 'center',
        activeTab	: 0,
        defaults	: {closable: true},
        items		: [{
            title		: 'Portal',
            closable	: false
        }]
    });
    
    //criar layout
    new Ext.Viewport({
    	 layout	: 'border'
    	,items	: [{
    	//menu lateral
    		 region			: 'west'
    		,layout			: 'accordion'
    		,defaultType	: 'treepanel'
    		,width			: 300
    		,split			: true
    		,layoutConfig	: {fill: false, animate:true}
    		,defaults		: {
    			 border		: false
    			,rootVisible: false
    			,listeners:{
    				 scope: this
    				,click: this.onNodeClick
    			}
    		}
    		,items			: [{
    			 title	: 'Cadastros'
    			,iconCls: 'silk-add'
    			,root	: {
    				children: [
    					 {text:'Atendentes'		, leaf:true, iconCls:'no-icon'}
    					,{text:'Solicitantes'	, leaf:true, iconCls:'no-icon'}
    					,{text:'Clientes'		, leaf:true, iconCls:'no-icon'}
    					,{text:'Representantes'	, leaf:true, iconCls:'no-icon'}
    					,{text:'Produtos'		, leaf:true, iconCls:'no-icon'}
    					,{text:'Distribuidores'	, leaf:true, iconCls:'no-icon'}
    					,{text:'Compromissos'	, leaf:true, iconCls:'no-icon'}
    				]
    			}
    		},{
    			 title	: 'Configurações'
    			,iconCls: 'silk-cog'
    			,root	: {
    				children: [
    					 {text:'Feriados'		  ,leaf:true,iconCls:'no-icon'}
    					,{text:'Permissões'		  ,leaf:true,iconCls:'no-icon'}
    					,{text:'Horários'		  ,leaf:true,iconCls:'no-icon'}
    					,{text:'Cargas'			  ,leaf:true,iconCls:'no-icon'}
    					,{text:'Acesso ao sistema',leaf:true,iconCls:'no-icon'}
    				]
    			}
    		},{
    			 title	: 'Relatórios'
    			,iconCls: 'silk-grid'
    			,root	: {
    				children: [
    					 {text:'Tempo Trabalhado por Atendente',leaf:true,iconCls:'no-icon'}
    					,{text:'Vendas por Cliente'			   ,leaf:true,iconCls:'no-icon'}
    					,{text:'Rotas de Distribuição'		   ,leaf:true,iconCls:'no-icon'}
    					,{text:'Performance dos Representantes',leaf:true,iconCls:'no-icon'}
    				]
    			}
    		}]
    	},
    	//tabpanel central
    	this.tabPanelCentral]
    });
  2. Perceba que pouco antes de definir os TreePanels eu associei uma função (listener) ao evento click a cada um deles. Essa função deve ser definida em nossa classe. A documentação do Ext nos diz quais os parâmetros receber nesse listener:

    //...
    ,listeners:{
    	 scope: this
    	,click: this.onNodeClick
    }
    
    //...
    ,onNodeClick: function( node )
    {
    	//aqui vai nossa rotina para criar as abas
    }
    
  3. Por fim, nessa função vou implementar uma regra de negócio. Nela vou tentar procurar uma aba com a mesma descrição do item de menu que foi clicado. Se não existir, eu crio com o método add, se existir eu somente ativo. Isso evita a criação de abas duplicadas.

    ,onNodeClick: function( node )
    {
    	var titulo = node.text;
    	var novaAba = this.tabPanelCentral.items.find(function( aba ){ return aba.title === titulo; });
    
    	if(!novaAba)
    	{
    		novaAba = this.tabPanelCentral.add({
    			  title	: titulo
    			 ,html	: 'nova aba:' +  titulo
    		});
    	}
    
    	this.tabPanelCentral.activate(novaAba);
    }

E pronto! Temos aí links em um menu lateral abrindo novas abas no tabPanel central sem duplicar as abas. Não irei abordar como carregar conteúdo nas abas, mas no código fonte fiz algumas observações que podem guiá-lo nessa tarefa. Além disso temos exemplos mais completos no blog que podem também lhe ajudar, como por exemplo o Crud Avançado e Carregar códig Ext sob demanda

Forte abraço e até a próxima!

server-side.zip

Código Completo

Demo Online

Demo Online

Paginação de dados com Ext

Sorry, this entry is only available in Português.

No contexto de desenvolvimento web a paginação de dados é um processo em que uma larga quantidade de dados é sub-dividida em fragmentos denominados páginas para permitir uma utilização mais eficiente da memória do servidor.

Os maiores desafios de um algoritmo para paginação é tratar o início, o fim, a divisão de páginas, o total de registros e a movimentação entre páginas. Em resumo, criar uma paginação é sinônimo de chatice e trabalho pesado… mas não para nós desenvolvedores Ext (:

Ext.PagingToolbar

O Ext implementa uma especialização de Toolbar chamado PagingToolbar. Em resumo é um toolbar com botões de movimentação no início e um texto, geralmente indicando o número de registros mostrados e o total, no final.

ext-pagingtoolbar

Primeiramente vamos configurá-lo da forma mais fácil possível, sem nenhuma personalização somente com os valores padrões do Ext. Após isso vamos nos aprofundar um pouquinho nas suas configurações.

O básico

Tudo começa com o servidor. Quando utilizamos o PagingToolbar o Ext requisita dados do servidor enviando junto na requisição os parâmetros start e limit.

ext-paging-request

Cabe ao servidor receber esses dados e realizar a paginação. Segue exemplo de paginação bem básica com PHP e MySQL:

//busca parâmetros de paginação informados pelo Ext
//caso seja vazio (1ª requisição) coloca valores default
$start = isset($_GET["start"]) ? (int)$_GET["start"]:0;
$limit = isset($_GET["limit"]) ? (int)$_GET["limit"]:20;

//busca total
$sql = "SELECT companyId FROM companies";
$rs = mysql_query($sql,$conn);
$num_total_registos = mysql_num_rows($rs);

//realiza consulta
$sql = "SELECT company,price,change,changePct,lastUpdate FROM companies LIMIT $start,$limit";
$rs = mysql_query($sql,$conn);

$arrJson = array();

//transfere pro arrJson
while ($registro = mysql_fetch_object($rs))
{
    $arrJson[] = array(
        "company"   => $registro->company,
        "price"     => $registro->price,
        "change"    => $registro->change,
        "changePct" => $registro->changePct,
        "lastUpdate"=> $registro->lastUpdate
    );
}

//responde
echo json_encode(array(
    "rows"  => $arrJson,
    "total" => $num_total_registos
));

Tudo começa com o servidor. Uma típica resposta do servidor está exemplificada abaixo. Repare que temos o array com 20 registros e um “total” indicando quantos registros existem no meu banco de dados. Esse total é necessário para que os cálculos de paginação sejam feitos corretamente. Já que o Ext vai receber somente 20 registros, ele precisa ter a informação do total.

{
    "rows":[
        {"company":"3m Co","price":71.72,"change":0.02,"changePct":0.03,"lastUpdate":"9/1 12:00am"},
        {"company":"Alcoa Inc","price":29.01,"change":0.42,"changePct":1.47,"lastUpdate":"9/1 12:00am"}
        //...restante dos 20 registros...//
    ],
    "total":29
}

IMPORTANTE: O pagingToolbar não realiza a paginação! Você tem que realizar a paginação no servidor através de SQL ou qualquer outra técnica.

Feito toda a rotina do servidor temos que criar DataStore para receber e gerenciar esses dados. O DataStore serve como meio-de-campo entre os dados do servidor e os componentes Ext. Abaixo tenho um JsonStore que pega a resposta JSON exemplificada acima e converte em registros Ext (record)

var dsEmpresas = new Ext.data.JsonStore({
    root : "rows",
    totalProperty : "total",
    remoteSort : true,
    sortInfo : {field: "company" ,direction: "ASC"},
    proxy : new Ext.data.HttpProxy({url: "ajax.php" ,method: "GET" }),
    fields : [
        {name: "company" ,type: "string" },
        {name: "price" ,type: "float" },
        {name: "change" ,type: "float" },
        {name: "changePct" ,type: "float" },
        {name: "lastUpdate",type: "date" ,dateFormat:'n/j h:ia'}
    ]
});

IMPORTANTE: O DataStore precisa ter declarado um valor para totalProperty. Essa é a propriedade servirá para extrair o total real de registros presentes no servidor.

Em seguida podemos criar um PagingToolbar bem básico. Importante notar que ele possui o número de registros por páginas (pageSize) e está associado ao store. O uso mais comum é colocar o toolbar num Grid, mas ele pode ser usado em um ComboBox paginado, ou até mesmo associado a um formulário configurado para mostrar 1 registro por página!

var pagingToolbar = new Ext.PagingToolbar({
    store : dsEmpresas,
    pageSize : 20,
    displayInfo : true
});

Este exemplo completo com o código está disponível na seção exemplos do portal. Ao fim desse artigo disponibilizo o link para acesso.

O avançado

Vamos ver agora algumas formas de personalizar o PagingToolbar e fazer algumas coisinhas a mais que o seu simples uso básico.

É possível alterar todos os textos e descrições padrões do PagingToolbar. Não vou comentar todas as propriedades (afterPageText, beforePageText,..) mas vou logo a mais importante que é displayMsg. Essa é a mensagem que aparece no final do Toolbar, e somente quando a propriedade displayInfo está setada como true. As vezes queremos dar ao usuário uma informação extra, que colocamos junto no JSON mas não sabemos como extrair para colocar no Toolbar. Podemos extrair a informação e concatenar ao displayMsg para apresentar ao usuário junto no toolbar. Seguindo o meu grid de empresas e cotações, segue um exemplo de como isso pode ser feito.

//Carrega o store
dsEmpresas.load({
    callback: function()
    {
        //quando o store terminar de carregar extrai a informação da
        //cotação da ibovespa e coloca junto no pagingToolbar

        pagingToolbar.displayMsg = "Índice Ibovespa:" +
        dsEmpresas.reader.jsonData.indiceBovespa +
        " - " + pagingToolbar.displayMsg;

        pagingToolbar.updateInfo();
    }
})

ext-pagingtoolbar-2

Essa é uma solução rápida. Uma mais profissional seria adicionar um item ao toolbar e usar esse item para mostrar a informação. Sendo assim levanto outra questão: como adicionar mais itens ao toolbar?

A partir da versão 3.0 o toolbar respeita a propriedade items. Basta ir adicionando itens e eles serão colocados no toolbar logo após os botões de navegação e antes da mensagem final (ou seja, no meio). É possível fazer eles serem adicionados no início atribuindo prependButtons como true. Então vamos adicionar um novo item, colocar um id nele e fazer com que nosso índice da bovespa apareca nesse item, ao invés de concatenar ao displayMsg.

var pagingToolbar = new Ext.PagingToolbar({
    store : dsEmpresas,
    pageSize : 20,
    displayInfo : true,
    beforePageText :"Página",
    afterPageText : " de {0}",
    items : [{
        xtype : "tbtext",
        id : "info-bovespa"
    }]
});

//..grid e etc...

//Carrega o store
dsEmpresas.load({
    callback: function()
    {
        Ext.getCmp("info-bovespa").setText( "Índice Ibovespa:" + dsEmpresas.reader.jsonData.indiceBovespa );
    }
});

Resumo

Espero com esse post ter deixado bem claro como realizar paginação de dados do Ext, e ainda configurar o PagingToolbar de uma maneira mais personalizada. Para não restar dúvida, segue checklist dos passos para criar uma paginação sem problemas:

  1. Servidor recebe start e limit e realiza a paginação. Retornando os dados mais o total de registros
  2. O DataStore que vai receber os dados está configurado corretamente. A configuração totalProperty não pode ser esquecida. Além disso, a ordenação para funcionar corretamente deve ser remota.
  3. O PagingToolbar está associado ao store. Se quiser informações mais detalhadas use displayMsg:true.

Agora basta associar o PaginToolbar a um grid, combo, formulário, etc…e sair usufruindo dessa excelente implementação do Ext.

Forte abraço e até a próxima!

server-side.zip

Código Completo

Demo Online

Demo Online