ExtJS 4 Exemplo MVC: Exemplo de Comboboxes Aninhados com PHP e MySQL
Em 2010 publiquei um tutorial sobre combobooxes aninhados, mas em ExtJS 3. Algumas coisas mudaram em ExtJS 4, então decidi fazer um update no tutorial. Mudei também a linguagem de backend de Java para PHP.
O que vai mudar entre o tutorial do ExtJS 3 e ExtJS 4 é apenas o frontend, ou seja, o código ExtJS. Se quiser pode usar o backend que fiz no post passado com o código do ExtJS 4 ou o código do ExtJS 3 com o backend feito em PHP deste post.
Vamos lá!
Estrutura do Projeto:
Código ExtJS 4:
Model – Estado
Ext.define('ExtMVC.model.State',{
extend: 'Ext.data.Model',
fields: [
{name: 'state_id'},
{name: 'state_name'}
],
idProperty: 'state_id'
});
Store – Estados
Ext.define('ExtMVC.store.States',{
extend: 'Ext.data.Store',
storeId: 'statesStore',
model: 'ExtMVC.model.State',
autoLoad:true,
proxy: {
type: 'ajax',
url: 'php/listStates.php',
reader: {
type: 'json',
root: 'data'
}
}
});
Model – Cidade
Ext.define('ExtMVC.model.City',{
extend: 'Ext.data.Model',
fields: [
{name: 'city_id'},
{name: 'state_id'},
{name: 'city_name'}
],
idProperty: 'city_id'
});
Store – Cidades
Ext.define('ExtMVC.store.Cities',{
extend: 'Ext.data.Store',
model: 'ExtMVC.model.City',
proxy: {
type: 'ajax',
url: 'php/listCities.php',
reader: {
type: 'json',
root: 'data'
}
}
});
View
Ext.define('ExtMVC.view.StateCityCombo' ,{
extend: 'Ext.form.Panel',
alias : 'widget.statecityform',
frame: true,
title:'Linked Comboboxes',
style:'margin:16px',
bodyStyle:'padding:10px',
fieldDefaults: {
labelAlign: 'right',
labelWidth: 85,
msgTarget: 'side'
},
items: [{
xtype: 'combo',
id: 'stateCombo',
fieldLabel:'Select State',
displayField:'state_name',
valueField:'state_id',
store: Ext.create('ExtMVC.store.States'),
triggerAction:'all',
queryMode:'local',
},
{
xtype: 'combo',
id: 'cityCombo',
fieldLabel:'Select City',
displayField:'city_name',
valueField:'city_id',
store: Ext.create('ExtMVC.store.Cities'),
triggerAction:'all',
queryMode:'local',
disabled:true,
lastQuery:''
}]
});
ViewPort
Ext.define('ExtMVC.view.Viewport', {
extend: 'Ext.Viewport',
layout: 'fit',
requires: [
'ExtMVC.view.StateCityCombo'
],
initComponent: function() {
var me = this;
Ext.apply(me, {
items: [
{
xtype: 'statecityform'
}
]
});
me.callParent(arguments);
}
});
Controller
Ext.define('ExtMVC.controller.LinkedComboboxes', {
extend: 'Ext.app.Controller',
models: ['State', 'City'],
stores: ['States', 'Cities'],
views: ['StateCityCombo'],
init: function() {
this.control({
'statecityform #stateCombo': {
select: this.loadCityCombo
}
});
},
loadCityCombo: function(combo, records) {
var comboCity = Ext.ComponentQuery.query('statecityform #cityCombo')[0];
comboCity.setDisabled(true);
comboCity.setValue('');
comboCity.store.removeAll();
comboCity.store.load({
params: { stateId: combo.getValue() }
});
comboCity.setDisabled(false);
}
});
App
Ext.Loader.setConfig({enabled: true});
Ext.application({
name: 'ExtMVC',
controllers: [
'LinkedComboboxes'
],
autoCreateViewport: true
});
listaEstados.php
<?php
//chama o arquivo de conexão com o bd
include("database.php");
//consulta sql
$query = mysql_query("SELECT * FROM State") or die(mysql_error());
//faz um looping e cria um array com os campos da consulta
$rows = array('data' => array());
while($state = mysql_fetch_assoc($query)) {
$rows['data'][] = $state;
}
//encoda para formato JSON
echo json_encode($rows);
?>
listaCidades.php
<?php
//chama o arquivo de conexão com o bd
include("database.php");
$stateId = $_REQUEST['stateId'];
$queryString = "SELECT * FROM City WHERE state_id = " . $stateId;
//consulta sql
$query = mysql_query($queryString) or die(mysql_error());
//faz um looping e cria um array com os campos da consulta
$rows = array('data' => array());
while($city = mysql_fetch_assoc($query)) {
$rows['data'][] = $city;
}
//encoda para formato JSON
echo json_encode($rows);
?>
Download do Código Fonte:
Você pode fazer o download do código fonte completo no meu repositório do github: https://github.com/loiane/extjs4-linked-combobox
Demo:
Exemplo funcionando: http://loiane.com/extjs/extjs4-linked-combobox/
Até a próxima!
Comments (19)
Links to this Post
- Exemplos Sencha ExtJS 4 em MVC | Loiane Groner | 29/05/2012











A página do link “Exemplo funcionando” não funciona. E já lhe adianto que é algo na conexão do PHP com o banco de dados ao obter os estados.
Mensagem de erro obtida via GDT:
Warning: mysql_connect() [function.mysql-connect]: Lost connection to MySQL server at ‘reading initial communication packet’, system error: 111 in /home/loiane/public_html/extjs/extjs4-linked-combobox/php/database.php on line 16
Lost connection to MySQL server at ‘reading initial communication packet’, system error: 111
Até mais!
Aff, esqueci de alterar a senha do banco do blog!
Valeu Paulo, vou olhar isso!
Muito bom o exemplo,
Sei que o exemplo é simples, porém gostaria de tirar uma dúvida referente ao uso do ID no componente, pois trabalho com o Ext3 e não utilizo o id devido na abertura de várias janelas pode acontecer de ter outro componente com o mesmo id em uma janela já aberta, ocasionando um erro durante a renderização.
Esse tipo de erro ocorre no Ext4?
Obrigado.
James,
Não é boa prática dar id aos componentes do extjs, exceto os casos em que isso é realmente necessário, como no caso desse exemplo.
No ExtJS 4 o problema vai continuar acontecendo, pois faz parte do ciclo de vida do componente do ExtJS, mas existem maneiras de se contornar isso.
Por isso que no ExtJS a gente usa o ComponentQuery e não Ext.getCmp.
Parabéns Loiane, muito bom o post… verifique depois o charset pois as cidades e estados com acentuação não estão aparecendo, o charset deve ser UTF-8.
Valeu Marcelo,
acertei o charset tb!
@James, @Loiane
No Ext 4 você pode usar o atributo itemId ao invés do id, assim é possível ter múltiplos componentes com o mesmo itemId (desde que estejam em containers diferentes). Você pode buscar elementos passando o itemId como parâmetro no método Ext.ComponentQuery.query.
Sim Eduardo,
Mas isso deve ser evitado ao máximo.
[]‘s
Opa, Loiane, supondo que esse combo faça parte de dois forms e eu carregue esse dois forms ao mesmo tempo no mesmo panel, pode acontecer de quando eu alterar o combo do form1 alterar também o valor do form2? Eu estou com esse problema quando, tento usar esse combo que vc criou em mais de um lugar o valor de um interfere no outro.
Oi Loiane, muito bom o exemplo.
Apenas uma dúvida, eu sou obrigado a colocar todos os controllers e models na Application? Eu sei que nesse momento ele carrega todas as classes.
Em uma aplicação grande isso não ficaria pesado.
Abraço, acompanho o seu trabalho e é simplesmente excelente!!!
Tenho aproveitado o maximo das suas aulas. Todas muito boas.
Obrigado Loiane
Olá, Loiane.
Fiz exatamente como no seu exemplo, porém na segunda vez que modifico o estado, quando seleciono o campo cidades o Ext fica no carregando e não sai, apenas de mostrar de fundo as cidades recuperadas para aquele estrado.
Ou seja, as cidades do novo estado já estão carregadas porém não consigo selecionar a cidade devido a estar o “Loading” na frente do campo.
Olá, baixei os códigos e ainda tem o problema do encodeamento json, como contornar isso ?
Loiane como faço para poder carregar os combobox apos eu salvar eles no banco, ai quando vou editar não sei como setar para o valor que ele recebe do banco
Oi Gustavo, dê uma olhada no método setValue
[]‘s
Olá Loiane, primeiramente meus parabéns pelo tutorial você contribui bastante para o mundo dos desenvolvedores e sua didática é sem palavras.
Sobre os combos você está mencionando o atributo “mode” que era utilizado no componente na versão ExtJS3, neste caso teria que ser o atributo “queryMode” para a versão ExtJS4.
Att.
Legolas
Valeu Legolas, vou acertar!
[]´s
Olá, Loiane. Parabéns pela iniciativa! Sugiro um acréscimo no código do database.php, de forma que seja evitado/corrigido o problema da acentuação. Nos testes que eu fiz, o “json” estava convertendo dados acentuados para “null”. Abs.
//executa a conexão com o banco, caso contrário mostra o erro ocorrido
$conexao = mysql_connect($servidor,$user,$senha) or die (mysql_error());
//incluir esta linha no código
mysql_set_charset(‘utf8′, $conexao);