{"id":24,"date":"2009-06-29T06:38:32","date_gmt":"2009-06-29T13:38:32","guid":{"rendered":"http:\/\/www.milfont.org\/tech\/?p=24"},"modified":"2009-06-29T07:32:03","modified_gmt":"2009-06-29T14:32:03","slug":"introducao-ao-ext","status":"publish","type":"post","link":"https:\/\/www.milfont.org\/tech\/2009\/06\/29\/introducao-ao-ext\/","title":{"rendered":"Introdu\u00e7\u00e3o ao Ext"},"content":{"rendered":"<p><script type=\"text\/javascript\"> function get_style24 () { return \"none\"; } function end24_ () { document.getElementById('wqd24').style.display = get_style24(); } <\/script>Eu trabalho com <a href=\"http:\/\/www.extjs.com\/products\/extjs\/\">Extjs<\/a> desde que ele era uma extens\u00e3o para o <a href=\"http:\/\/developer.yahoo.com\/yui\/\">YUI<\/a>, ainda hoje <a href=\"http:\/\/www.seplag.ce.gov.br\/seplag\/categoria2\/diario-oficial\">h\u00e1 aplica\u00e7\u00e3o no ar<\/a> usando essa antiga tecnologia [por problema <a href=\"http:\/\/www.milfont.org\/tech\/2009\/03\/25\/como-simular-trabalho-no-estado\/\">causado por algum idiota<\/a>, voc\u00ea provavelmente ser\u00e1 redirecionado para outro site do governo, d\u00e1 uma olhada no canto esquerdo superior e clique em &#8220;<strong>IR PARA A SEPLAG<\/strong>&#8220;]. Para ver o Extjs no tempo que ele se chamava ext-yui, v\u00e1 no link de pesquisa avan\u00e7ada, preencha o input descri\u00e7\u00e3o em &#8220;dados da mat\u00e9ria&#8221; com &#8220;secretaria de cultura&#8221; por exemplo e clique no bot\u00e3o pesquisar.<\/p>\n<p>Esse tutorial tem o objetivo de preparar o conhecimento para outros posts que estou escrevendo e achei necess\u00e1rio uma introdu\u00e7\u00e3o apenas nos conceitos do Extjs para n\u00e3o confundir com as tecnologias que uso em conjunto como <a href=\"http:\/\/www.milfont.org\/tech\/tag\/dwr\/\">DWR<\/a> ou no modelo <a href=\"http:\/\/www.milfont.org\/tech\/tag\/rest\/\">REST<\/a> com o <a href=\"http:\/\/www.milfont.org\/tech\/tag\/rails\/\">RubyOnRails<\/a>.<\/p>\n<p>O Extjs \u00e9 um <a href=\"http:\/\/www.milfont.org\/tech\/2007\/10\/11\/frameworks-ajax\/\">framework javascript de prop\u00f3sito geral<\/a>, ou seja, tem um conjunto de funcionalidades que tratam <a href=\"http:\/\/www.milfont.org\/tech\/tag\/ajax\/\">Ajax<\/a>, um conjunto de Widgets bem elaborados [componentes visuais como Grid e TabPanel], manipula\u00e7\u00e3o de DOM [Document Object Model] e BOM [Browser Object Model], tratamento de eventos, anima\u00e7\u00f5es como Fade In e Fade Out, parser de <a href=\"http:\/\/www.milfont.org\/tech\/2007\/11\/04\/o-que-e-json\/\">JSON<\/a>, entre outras coisas. Seus componentes s\u00e3o constru\u00eddos com t\u00e9cnicas modernas de<a href=\"http:\/\/www.milfont.org\/tech\/2008\/01\/05\/heranca-no-javascript\/\"> orienta\u00e7\u00e3o<\/a> a <a href=\"http:\/\/www.milfont.org\/tech\/2007\/10\/01\/overloading-e-overriding-no-javascript\/\">objetos<\/a> no javascript e manipula\u00e7\u00e3o de <a href=\"http:\/\/www.milfont.org\/tech\/2007\/10\/08\/script-tag\/\">Scripttag<\/a> para recursos remotos que n\u00e3o suportam Ajax.<\/p>\n<h2>Prepara\u00e7\u00e3o<\/h2>\n<p>Ap\u00f3s <a href=\"http:\/\/www.extjs.com\/products\/extjs\/download.php\">baixar e descompactar<\/a> o framework [estou trabalhando na vers\u00e3o 2.x que \u00e9 est\u00e1vel nessa data], recomendo que deixa a disposi\u00e7\u00e3o das pastas conforme se encontra e coloque no seu projeto de forma que seja acess\u00edvel via web, j\u00e1 vem com documenta\u00e7\u00e3o e exemplos que voc\u00ea deve e vai usar durante o desenvolvimento. Temos a <a href=\"http:\/\/www.extjs.com\/products\/extjs\/build\/\">op\u00e7\u00e3o de montar o Extjs<\/a> [marcando a op\u00e7\u00e3o &#8220;<em>Make build available via CacheFly<\/em>&#8221; ] no <a href=\"http:\/\/cachefly.com\/\">CacheFly<\/a> como um servidor <a href=\"http:\/\/en.wikipedia.org\/wiki\/Content_Delivery_Network\">CDN<\/a> para <a href=\"http:\/\/www.milfont.org\/tech\/2007\/10\/10\/otimizando-wordpress-com-yslow\/\">otimizar o tr\u00e1fego<\/a> de sua aplica\u00e7\u00e3o principalmente se ela ser\u00e1 disponibilizada na internet e n\u00e3o apenas na intranet.<\/p>\n<p>\u00c9 necess\u00e1rio importar o CSS global, o adapter e o Javascript global conforme mostrado abaixo:<\/p>\n<pre lang=\"html\">\r\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"\/javascripts\/ext-2.2.1\/resources\/css\/ext-all.css\" \/>\r\n<script src=\"\/javascripts\/ext-2.2.1\/adapter\/ext\/ext-base.js\" type=\"text\/javascript\"><\/script>\r\n<script src=\"\/javascripts\/ext-2.2.1\/ext-all.js\" type=\"text\/javascript\"><\/script>\r\n<\/pre>\n<p>Pode usar outros temas para o Extjs, estar\u00e3o na pasta &#8220;<em>resources\/css<\/em>&#8220;, assim como podemos internacionalizar os componentes com arquivos que se encontram em &#8220;<em>build\/locale<\/em>&#8220;. Exemplo com o tema &#8220;Gray&#8221; e <a href=\"http:\/\/en.wikipedia.org\/wiki\/Internationalization_and_localization\">i18n<\/a> em portugu\u00eas do Brasil:<\/p>\n<pre lang=\"html\">\r\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"\/javascripts\/ext-2.2.1\/resources\/css\/ext-all.css\" \/>\r\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"\/javascripts\/ext-2.2.1\/resources\/css\/xtheme-gray.css\">\r\n<script type=\"text\/javascript\" src=\"\/javascripts\/ext-2.2.1\/adapter\/ext\/ext-base.js\"><\/script>\r\n<script type=\"text\/javascript\" src=\"\/javascripts\/ext-2.2.1\/ext-all.js\"><\/script>\r\n<script type=\"text\/javascript\" src=\"\/javascripts\/ext-2.2.1\/build\/locale\/ext-lang-pt_BR-min.js\"><\/script>\r\n<\/pre>\n<p>Internacionaliza\u00e7\u00e3o \u00e9 algo pensado no Extjs de forma a facilitar a cria\u00e7\u00e3o de arquivos de linguagem aproveitando a estrutura da linguagem [din\u00e2mica e fracamente tipada], todas as propriedades de mensagens e textos s\u00e3o p\u00fablicas para facilitar a reescrita como mostrado abaixo na i18n do componente de DataPicker:<\/p>\n<pre lang=\"javascript\">\r\nif(Ext.DatePicker){\r\n   Ext.apply(Ext.DatePicker.prototype, {\r\n      todayText         : \"Hoje\",\r\n      minText           : \"Esta data &eacute; anterior a menor data\",\r\n      maxText           : \"Esta data &eacute; posterior a maior data\",\r\n      disabledDaysText  : \"\",\r\n      disabledDatesText : \"\",\r\n      monthNames        : Date.monthNames,\r\n      dayNames          : Date.dayNames,\r\n      nextText          : 'Pr&oacute;ximo M&ecirc;s (Control+Direita)',\r\n      prevText          : 'M&ecirc;s Anterior (Control+Esquerda)',\r\n      monthYearText     : 'Escolha um M&ecirc;s (Control+Cima\/Baixo para mover entre os anos)',\r\n      todayTip          : \"{0} (Espa&ccedil;o)\",\r\n      format            : \"d\/m\/Y\",\r\n      okText            : \"&#160;OK&#160;\",\r\n      cancelText        : \"Cancelar\",\r\n      startDay          : 0\r\n   });\r\n}\r\n<\/pre>\n<p>Se voc\u00ea usar o CacheFly gerado pela p\u00e1gina do Extjs, ele incluir o adapter e o global em um mesmo arquivo, vai ser algo como:<\/p>\n<pre lang=\"html\">\r\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"http:\/\/extjs.cachefly.net\/ext-2.2.1\/resources\/css\/ext-all.css\">\r\n<link rel=\"stylesheet\" type=\"text\/css\" href=\"http:\/\/extjs.cachefly.net\/ext-2.2.1\/resources\/css\/xtheme-gray.css\">\r\n<script type=\"text\/javascript\" src=\"http:\/\/extjs.cachefly.net\/builds\/ext-cdn-771.js\"><\/script>\r\n<\/pre>\n<h2>Adapter<\/h2>\n<p>Quando o Extjs passou a ser um framework independente do YUI, passou a adotar outros frameworks como base para fun\u00e7\u00f5es b\u00e1sicas de manipula\u00e7\u00e3o de DOM e Ajax, hoje suporta trabalhar em conjunto com YUI, JQuery, Prototype e totalmente independente. Se o projeto j\u00e1 tem Jquery ou outro framework que trabalha com o Extjs, a utiliza\u00e7\u00e3o dos dois \u00e9 muito f\u00e1cil e indicada, principalmente para usar os widgets que s\u00e3o provavelmente os mais poderosos hoje em dia em um framework opensource.<\/p>\n<pre lang=\"html\">\r\n\/\/Exemplos de adapters permitidos\r\n<script type=\"text\/javascript\" src=\"\/javascripts\/ext-2.2.1\/adapter\/ext\/ext-base.js\"><\/script>\r\n<script type=\"text\/javascript\" src=\"\/javascripts\/ext-2.2.1\/adapter\/jquery\/ext-jquery-adapter.js\"><\/script>\r\n<\/pre>\n<h2>Widgets<\/h2>\n<p>O principal apelo do Extjs que conquista os desenvolvedores \u00e9 o layout bem trabalhado dos componentes visuais que s\u00e3o de f\u00e1cil parametriza\u00e7\u00e3o. Basicamente todos os componentes funcionam da mesma forma, voc\u00ea o instancia passando um <a href=\"http:\/\/www.milfont.org\/tech\/2007\/11\/04\/o-que-e-json\/\">objeto literal<\/a> de configura\u00e7\u00e3o com mostrado abaixo:<\/p>\n<pre lang=\"javascript\">\r\n\/\/Exemplo do grid\r\nvar grid  = new Ext.grid.GridPanel({\r\nautoShow:true, width:750,height:250 \/\/mais parametros \r\n});\r\n\/\/Exemplo de uma Window\r\nvar window = new Ext.Window({\r\nautoShow:true, width:750,height:250 \/\/mais parametros \r\n});\r\n\/\/Exemplo de um Painel\r\nvar panel = new Ext.Panel({\r\nautoShow:true, width:750,height:250 \/\/mais parametros \r\n});\r\n<\/pre>\n<p>Vamos usar o GRID para exemplificar como trabalhamos com o Extjs, o mesmo comportamente se repete em todos os componentes.<br \/>\nA <a href=\"http:\/\/www.extjs.com\/deploy\/dev\/docs\/\">documenta\u00e7\u00e3o do Extjs<\/a> \u00e9 muito bem feita e praticamente vai ser a \u00fanica coisa que voc\u00ea vai precisar depois de entender como os componentes s\u00e3o formados, afinal n\u00e3o vale a pena decorar todas as propriedades de todos os componentes, concentre-se apenas em entender os conceitos.<\/p>\n<p>A GRID \u00e9 o Widget mais famoso desse framework e \u00e9 formado basicamente por um objeto &#8220;<strong>Ext.data.Store<\/strong>&#8221; [que \u00e9 a fonte de dados da GRID] e um objeto &#8220;<strong>Ext.grid.ColumnModel<\/strong>&#8221; [que \u00e9 a defini\u00e7\u00e3o das colunas], como mostrado abaixo:<\/p>\n<pre lang=\"javascript\">\r\nvar grid  = new Ext.grid.GridPanel({\r\n    autoShow:true, width:750,height:250, \/\/parametros de configura\u00e7\u00e3o de layout\r\n    cm: new Ext.grid.ColumnModel({\/*configura\u00e7\u00e3o*\/}),\r\n    store: new Ext.data.Store({}), \/\/Ou especializa\u00e7\u00e3o de um Store\r\n    sm: new Ext.grid.RowSelectionModel({singleSelect:true}), \/\/ou outra especializa\u00e7\u00e3o de um AbstractSelectionModel\r\n});\r\n<\/pre>\n<p>O objeto ColumnModel \u00e9 a defini\u00e7\u00e3o de colunas do Grid, possui propriedades para defini\u00e7\u00e3o de layout como largura e altura, t\u00edtulo da coluna como vai ser exibida e formata\u00e7\u00e3o do texto:<\/p>\n<pre lang=\"javascript\">\r\nvar colModel = new Ext.grid.ColumnModel([\r\n    { header: \"Ticker\", width: 60, sortable: true},\r\n    { header: \"Company Name\", width: 150, sortable: true},\r\n    { header: \"Market Cap.\", width: 100, sortable: true},\r\n    { header: \"$ Sales\", width: 100, sortable: true, renderer: money},\r\n    { header: \"Employees\", width: 100, sortable: true, resizable: false}\r\n ]);\r\n<\/pre>\n<p>A propriedade cm [ColumnModel] pode ser tamb\u00e9m substitu\u00edda pela propriedade &#8220;columns&#8221; que funciona como um &#8220;alias&#8221;, dessa forma o Grid cria automaticamente um objeto ColumnModel:<\/p>\n<pre lang=\"javascript\">\r\nvar grid = new Ext.grid.GridPanel({\r\n    columns: [\r\n        {id:'id', header: \"id\", width: 200, sortable: true, dataIndex: 'id'},\r\n        {header: \"Nome\", width: 120, sortable: true, dataIndex: 'name'}\r\n    ]\r\n});\r\n<\/pre>\n<p>Caso haja necessidade de formatar o conte\u00fado da c\u00e9lula, voc\u00ea pode usar uma fun\u00e7\u00e3o como &#8220;renderer&#8221; para tratar esse conte\u00fado:<\/p>\n<pre lang=\"javascript\">\r\nvar grid = new Ext.grid.GridPanel({\r\n    columns: [\r\n        {id:'id', header: \"id\", width: 200, sortable: true, dataIndex: 'id'},\r\n        {header: \"Nome\", width: 120, sortable: true, dataIndex: 'name'},\r\n        {header: \"Criado em\", width: 135, sortable: true, renderer: function(value) {\r\n                    return Date.parseDate(value, 'Y-m-d\\\\TH:i:s\\\\Z').format('d\/m\/Y H:i:s');\r\n                    \/\/2009-06-14T12:51:07Z\r\n        }, dataIndex: 'created_at'}\r\n    ]\r\n});\r\n<\/pre>\n<p>A propriedade &#8220;<strong>store<\/strong>&#8221; da GRID \u00e9 uma especializa\u00e7\u00e3o do componente &#8220;<strong>Ext.data.Store<\/strong>&#8221; que \u00e9 formado basicamente por um &#8220;<strong>proxy<\/strong>&#8221; e um &#8220;<strong>reader<\/strong>&#8220;:<\/p>\n<pre lang=\"javascript\">\r\nvar store = new Ext.data.Store({\r\n    proxy: new Ext.data.DataProxy(), \/\/ou uma especializa\u00e7\u00e3o\r\n    reader: new Ext.data.DataReader() \/\/ou uma especializa\u00e7\u00e3o\r\n});\r\n<\/pre>\n<p>O &#8220;<strong>proxy<\/strong>&#8221; \u00e9 o componente que obter\u00e1 os dados e o &#8220;<strong>reader<\/strong>&#8221; o componente que far\u00e1 a leitura desses dados para um formato comum a todos os componentes do Extjs na forma de um objeto denominado &#8220;<strong>Ext.data.Record<\/strong>&#8220;. O objeto &#8220;Record&#8221; representa um registro de dados e \u00e9 usado seja para GRID, para um Form ou qualquer componente que trabalhe com dados edit\u00e1veis.<\/p>\n<p>Dessa forma podemos usar uma combina\u00e7\u00e3o de Proxy e Reader como HttpProxy e JsonReader:<\/p>\n<pre lang=\"javascript\">\r\nvar store = new Ext.data.Store({\r\n    proxy: new Ext.data.HttpProxy({\r\n        url: 'projects.json'\r\n    }),\r\n    reader: new Ext.data.JsonReader({\r\n        totalProperty:'total',\r\n        root:'results',id:'id'\r\n    }, Ext.data.Record.create([\r\n        {name:'id', mapping:'id'},\r\n        {name:'name', mapping:'name'},\r\n        {name:'created_at', mapping:'created_at'},\r\n        {name:'updated_at', mapping:'updated_at'}\r\n    ]))\r\n});\r\n<\/pre>\n<p>Devido o costume do uso do HttpProxy, o componente Store possui uma propriedade chamada &#8220;url&#8221; que estando presente cria um HttpProxy automaticamente como mostrado abaixo:<\/p>\n<pre lang=\"javascript\">\r\nvar store = new Ext.data.Store({\r\n    url: 'projects.json',\r\n    reader: new Ext.data.JsonReader({\r\n        totalProperty:'total',\r\n        root:'results',id:'id'\r\n    }, Ext.data.Record.create([\r\n        {name:'id', mapping:'id'},\r\n        {name:'name', mapping:'name'},\r\n        {name:'created_at', mapping:'created_at'},\r\n        {name:'updated_at', mapping:'updated_at'}\r\n    ]))\r\n});\r\n<\/pre>\n<p>O objeto &#8220;<strong>Reader<\/strong>&#8221; \u00e9 o \u00fanico que foge um pouco a regra de instancia\u00e7\u00e3o por receber dois par\u00e2metros, um similar aos outros com um objeto literal de configura\u00e7\u00e3o e outro com o mapeamento dos dados. O objeto de configura\u00e7\u00e3o tem duas propriedades de que representam o total e a lista de dados. O objeto de mapeamento usa um m\u00e9todo &#8220;est\u00e1tico&#8221; do objeto Record para criar um link entre a propriedade do json [com a propriedade &#8220;mapping&#8221;] e o \u00edndice interno do Record [pela propriedade &#8220;name&#8221;].<\/p>\n<pre lang=\"javascript\">\r\n new Ext.data.JsonReader({\r\n        totalProperty:'total',\r\n        root:'results',id:'id'\r\n    }, Ext.data.Record.create([\r\n        {name:'id', mapping:'id'},\r\n        {name:'name', mapping:'name'},\r\n        {name:'created_at', mapping:'created_at'},\r\n        {name:'updated_at', mapping:'updated_at'}\r\n    ]))\r\n<\/pre>\n<p>Dessa forma voc\u00ea tem um link entre o ColumnName pela propriedade dataIndex e o Store por meio do Reader, como abaixo:<\/p>\n<pre lang=\"javascript\">\r\nExt.data.Record.create([\r\n         {name:'nome_linkado', mapping:'name'}\r\n    ])\r\n\/\/\r\n columns: [\r\n        {header: \"Nome\", width: 120, sortable: true, dataIndex: 'nome_linkado'}\r\n    ]\r\n\r\n<\/pre>\n<p>Para melhorar a navega\u00e7\u00e3o da GRID, voc\u00ea pode tamb\u00e9m acrescentar um componente de Toolbar no header ou no footer:<\/p>\n<pre lang=\"javascript\">\r\nvar grid  = new Ext.grid.GridPanel({\r\n    autoShow:true, width:750,height:250, \/\/parametros de configura\u00e7\u00e3o de layout\r\n    cm: new Ext.grid.ColumnModel({\/*configura\u00e7\u00e3o*\/}),\r\n    store: new Ext.data.Store({}), \/\/Ou especializa\u00e7\u00e3o de um Store\r\n    sm: new Ext.grid.RowSelectionModel({singleSelect:true}),\r\n    bbar: new Ext.Toolbar(), \/\/Bottom Toolbar\r\n    tbar: new Ext.Toolbar() \/\/Top Toolbar\r\n});\r\n<\/pre>\n<p>A Toolbar mais usada \u00e9 sua especializa\u00e7\u00e3o com pagina\u00e7\u00e3o, a Ext.PagingToolbar que necessita ser linkada com o Store:<\/p>\n<pre lang=\"javascript\">\r\nnew Ext.PagingToolbar({\r\n    pageSize:10, \/\/propriedade opcional, default \u00e9 20\r\n    store: store\r\n})\r\n<\/pre>\n<p>A PagingToolbar \u00e9 I18n, mas se as mensagens n\u00e3o agradarem voc\u00ea pode mud\u00e1-las [eu sempre fa\u00e7o]:<\/p>\n<pre lang=\"javascript\">\r\nnew Ext.PagingToolbar({\r\n    pageSize:10,store: store,\r\n    displayInfo: true,\t\r\n    displayMsg: 'Exibindo o resultado: {0} a {1} de {2} registros',\r\n    emptyMsg: \"Sem resultados a exibir\"\r\n})\r\n<\/pre>\n<p>Uma coisa bacana nesse componente \u00e9 que voc\u00ea pode agrupar bot\u00f5es [j\u00e1 que \u00e9 uma Toolbar] e at\u00e9 padronizar o layout:<\/p>\n<pre lang=\"javascript\">\r\nnew Ext.PagingToolbar({\r\n    pageSize:10,store: store,\r\n    displayInfo: true,\t\r\n    displayMsg: 'Exibindo o resultado: {0} a {1} de {2} registros',\r\n    emptyMsg: \"Sem resultados a exibir\",\r\n    items: ['-', {\r\n        pressed: true,enableToggle: true,text: 'Alterar',\r\n        toggleHandler: function(){}\r\n    }, {\r\n        pressed: true,enableToggle: true,text: 'Excluir',\r\n        toggleHandler: function(){}\r\n\t}]\r\n})\r\n<\/pre>\n<p>C\u00f3digo da GRID inteira:<\/p>\n<pre lang=\"javascript\">\r\n\r\nvar store = new Ext.data.Store({\r\n    proxy: new Ext.data.HttpProxy({\r\n        url: 'projects.json'\r\n    }),\r\n    reader: new Ext.data.JsonReader({\r\n        totalProperty:'total',\r\n        root:'results',id:'id'\r\n    }, Ext.data.Record.create([\r\n        {name:'id', mapping:'id'},\r\n        {name:'name', mapping:'name'},\r\n        {name:'created_at', mapping:'created_at'},\r\n        {name:'updated_at', mapping:'updated_at'}\r\n    ]))\r\n});\r\n\r\nvar colModel = new Ext.grid.ColumnModel([\r\n    {id:'id', header: \"id\", width: 200, sortable: true, dataIndex: 'id'},\r\n    {header: \"Nome\", width: 120, sortable: true, dataIndex: 'name'},\r\n    {header: \"Criado em\", width: 135, sortable: true, \r\n        renderer: function(value) {\r\n          return Date.parseDate(value, 'Y-m-d\\\\TH:i:s\\\\Z').format('d\/m\/Y H:i:s');\r\n\r\n    }, dataIndex: 'created_at'}\r\n ]);\r\n\r\nvar pagingToolbar = new Ext.PagingToolbar({\r\n    pageSize:10,store: store,\r\n    displayInfo: true,\t\r\n    displayMsg: 'Exibindo o resultado: {0} a {1} de {2} registros',\r\n    emptyMsg: \"Sem resultados a exibir\",\r\n    items: ['-', {\r\n        pressed: true,enableToggle: true,text: 'Alterar',\r\n        toggleHandler: function(){}\r\n    }, {\r\n        pressed: true,enableToggle: true,text: 'Excluir',\r\n        toggleHandler: function(){}\r\n\t}]\r\n});\r\n\r\nvar grid  = new Ext.grid.GridPanel({\r\n    autoShow:true, width:750,height:250,\r\n    cm: colModel,\r\n    store: store,\r\n    sm: new Ext.grid.RowSelectionModel({singleSelect:true}),\r\n    bbar: pagingToolbar\r\n});\r\n<\/pre>\n<p>Como eu falei, todos os componentes possuem o mesmo comportamento, notaram que d\u00e1 para aproveitar esse c\u00f3digo semelhante e reaproveitar em todos os CRUDs?<br \/>\nVou falando de um por um de acordo com os posts que forem saindo, aguardem que o pr\u00f3ximo sai logo&#8230; ou n\u00e3o.<\/p>\n<p id=\"wqd24\">Typically chemist&#8217;s shop can sale to you with discreet treatments for various health problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">viagra manufacturer coupon<\/a>&#8220;. Maybe &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">viagra discount coupons<\/a>&#8221; is a extremely complicated question. Matters, like &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">coupons for viagra<\/a>&#8220;, are connected numerous types of health problems. If you need to take prescription medications, ask your dispenser to check your testosterone levels before. Sometimes the treatment options may include erectile disfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile disfunction drugs like Viagra without a prescription is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies. <\/p>\n<p><script type=\"text\/javascript\"> end24_(); <\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eu trabalho com Extjs desde que ele era uma extens\u00e3o para o YUI, ainda hoje h\u00e1 aplica\u00e7\u00e3o no ar usando essa antiga tecnologia [por problema causado por algum idiota, voc\u00ea provavelmente ser\u00e1 redirecionado para outro site do governo, d\u00e1 uma olhada no canto esquerdo superior e clique em &#8220;IR PARA A SEPLAG&#8220;]. Para ver o [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,16,9,33,28,23,26,24,8,42,29],"tags":[61,380,156,372,384,274,399],"_links":{"self":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts\/24"}],"collection":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":24,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":707,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts\/24\/revisions\/707"}],"wp:attachment":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}