lucaswxp 22 Denunciar post Postado Outubro 19, 2009 Olá pessoal, continuando com os tutoriais sobre Ajax. Neste tutorial mostrarei algo que é bem procurado. Popular um combobox (selectbox) através da escolha de outro. Utilizaremos aqui um exemplo de categoria-subcategoria. Pré-requisitos * Conhecimento básico sobre o framework CakePHP * Conhecimento básico sobre o helper Ajax Conteúdo Vamos começar criandos nossas tabelas e inserindo alguns dados: CREATE TABLE `categorias` ( `id` int(11) NOT NULL auto_increment, `title` varchar(255) NOT NULL default '', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; INSERT INTO `categorias` VALUES (1,'Música'); INSERT INTO `categorias` VALUES (2,'Esporte'); INSERT INTO `categorias` VALUES (3,'Eletrodomesticos'); INSERT INTO `categorias` VALUES (4,'Móveis'); INSERT INTO `categorias` VALUES (5,'Outros'); CREATE TABLE `subcategorias` ( `id` int(11) NOT NULL auto_increment, `title` varchar(255) default NULL, `categoria_id` int(11) default NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; INSERT INTO `subcategorias` VALUES (1,'CD\'s',1); INSERT INTO `subcategorias` VALUES (2,'Guitarra',1); INSERT INTO `subcategorias` VALUES (3,'Bateria',1); INSERT INTO `subcategorias` VALUES (4,'Futebol',2); INSERT INTO `subcategorias` VALUES (5,'Cadeiras',4); INSERT INTO `subcategorias` VALUES (6,'Microondas',3); INSERT INTO `subcategorias` VALUES (7,'Bolas',2); E agora os models: <?php class Categoria extends AppModel { var $name = 'Categoria'; var $hasMany = 'Subcategoria'; } ?> <?php class Subcategoria extends AppModel { var $name = 'Subcategoria'; var $belongsTo = 'Categoria'; } ?> E os controllers: <?php class SubcategoriasController extends AppController { var $name = 'Subcategorias'; var $helpers = array('Html', 'Form','Javascript','Ajax'); } ?> <?php class CategoriasController extends AppController { var $name = 'Categorias'; } ?> Já temos uma estrutura básica, agora vamos criar a action/view responsavél pelo formulario que conterá os comboboxes das categorias-subcategorias. Action: <?php class SubcategoriasController extends AppController { var $name = 'Subcategorias'; var $helpers = array('Html', 'Form','Javascript','Ajax'); var $uses = array('Categoria','Subcategoria'); function show(){ $categorias = $this->Categoria->find('list'); // Listamos todas as categorias $this->set('categorias' , $categorias); } } ?> View: <?php $javascript->link('prototype' , false); // Incluimos o prototype echo $form->create(); echo $form->input('categoria' , array('id' => 'categoriaID')); // Listamos as categorias echo $form->input('subcategoria' , array('id' => 'subcategoriaID' , 'type' => 'select')); // Listamos as subcategorias echo $form->end(); $options = array( 'url' => array('controller' => 'subcategorias' , 'action' => 'buscaSubcategorias'), // Action a ser chamado 'update' => 'subcategoriaID', // ID do elemento a se atualizar ); echo $ajax->observeField('categoriaID' , $options) // Observamos o elemento com ID "categoriaID" ?> Aqui começamos incluindo o framework prototype. Logo após criamos os campos categoria e subcategoria que são os comboboxes, como você já deve saber - ou deveria xD - o único a ser populado por padrão é categoria, pois foi o único setado na action show() e por este motivo o type de subcategoria deve ser setado como select. Depois criamos uma variável $options que servirá como parametro para Ajax::observeField(). Esta variável contém o índice update que é o ID do elemento a ser atualizado e também contém o índice url que é a action a chamar quando Ajax::observeField() for acionado. E finalmente utilizamos o método que efetua a mágica. Ajax::observeField(), o primeiro parâmetro deve conter o ID do elemento a se observar e o segundo um array de opções ajax que criamos logo acima. Quando o combobox categoria for alterado, será chamado a action buscaSubcategorias do controller Subcategorias. Esta action será responsável por pega a categoria selecionada e em base disso buscar as subcategorias que pertencem a aquela categoria. Vamos lá: <?php class SubcategoriasController extends AppController { var $name = 'Subcategorias'; var $helpers = array('Html', 'Form','Javascript','Ajax'); var $uses = array('Categoria','Subcategoria'); function index() { $this->Subcategoria->recursive = 0; $this->set('subcategorias', $this->paginate()); } function view($id = null) { if (!$id) { $this->flash(__('Subcategoria inválida', true), array('action'=>'index')); } $this->set('subcategoria', $this->Subcategoria->read(null, $id)); } function buscaSubcategorias() { $this->layout = 'ajax'; // Utilizamos layout ajax $catID = $this->data['Categoria']['categoria']; // Pegamos o id da categorias selecionada $subcategorias = $this->Subcategoria->find('list' , array('conditions' => array('Subcategoria.categoria_id' => $catID))); // Encontramos todas as subcategorias que pertencem a $catID foreach($subcategorias as $key => $subcat){ // Iteramos, e devolvemos os options do selectbox echo "<option value=\"{$key}\">{$subcat}</option>"; } } ?> E voilà! Agora está pronto! Em buscaSubcategorias() imprimimos um conjunto de options, assim atualizando o valor do combobox subcategoria, simples assim. =D É isso ai pessoal, espero que tenham gostado, até a próxima o/ FONTE: http://lucaspelegrino.com/ Compartilhar este post Link para o post Compartilhar em outros sites
Mário Monteiro 179 Denunciar post Postado Dezembro 20, 2009 Esta colaborando bem aqui em cake Compartilhar este post Link para o post Compartilhar em outros sites
lucaswxp 22 Denunciar post Postado Dezembro 22, 2009 Vlw :) Compartilhar este post Link para o post Compartilhar em outros sites
~Thiago Lara 0 Denunciar post Postado Fevereiro 1, 2010 Opa, lucas, você tem ideia como utilizaria este caso em que a estrutura da tabela esteja em TREE? Compartilhar este post Link para o post Compartilhar em outros sites
lucaswxp 22 Denunciar post Postado Fevereiro 1, 2010 Hm... De mais detalhes do que ter de diferença significativa, a estrutura etc... =) (lembrando que tem o TreeBehavior pra lhe ajudar a formar o Tree) PS: De preferencia abra um novo topico Compartilhar este post Link para o post Compartilhar em outros sites
~Thiago Lara 0 Denunciar post Postado Fevereiro 9, 2010 Ótimo Lucas, conforme sugerido, http://forum.imasters.com.br/index.php?/topic/381178-o-behavior-tree/ Estive olhando o código Lucas e dê uma olhada no controller da categoria, está escrito "Categories", dá uma arrumada ae ;) Compartilhar este post Link para o post Compartilhar em outros sites
lucaswxp 22 Denunciar post Postado Fevereiro 9, 2010 Fixed. Isso que da usar o bake =P Compartilhar este post Link para o post Compartilhar em outros sites
tonylima 0 Denunciar post Postado Setembro 10, 2014 Caro lucas, Estou com um problema que se encaixa perfeitamente nesta solucao so nao estou conseguindo implementar, veja: Tenho uma view usuarios/add que cadastra os dados do usuario, este possui um cargo, que a partir deste cargo seleciona as classes relativas a ele, e a partir da classe selecionada, exibe as funcoes relativas a classe. minha view usuarios/add ate agora: <div class="col-md-8"> <div class="usuarios form"> <?php $javascript->link('prototype' , false); echo $this->Form->create('Usuario', array( 'inputDefaults' => array( 'label' => false, 'div' => false ) )); ?> <fieldset> <?php echo $this->Session->flash(); ?> <?php if (isset($this->request->data['Usuario']['matricula'])): ?> <?php else: ?> <legend>Adicionar Usuário</legend> <?php endif; ?> <div class="form-group"> <label class="required">Nome:</label> <?php echo $this->Form->input('nome', array('type' => 'text', 'class' => 'form-control uppercase', 'required' => true)); ?> </div> <div class="form-group"> <label class="required">Matricula:</label> <?php echo $this->Form->input('matricula', array('class' => 'form-control uppercase', 'required' => true)); ?> </div> <?php if (!isset($this->request->data['Usuario']['matricula'])): ?> <div class="form-group"> <label class="required">CPF:</label> <?php echo $this->Form->input('cpf', array('class' => 'form-control cpf', 'required' => true)); ?> </div> <?php else: ?> <div class="form-group"> <label>CPF:</label> <?php echo $this->Form->input('cpf', array('class' => 'form-control cpf')); ?> </div> <?php endif; ?> <div class="form-group"> <label class="required">Email:</label> <?php echo $this->Form->input('email', array('type'=>'email','class' => 'form-control', 'required' => true)); ?> </div> <div class="form-group"> <label class="required">Login:</label> <?php echo $this->Form->input('username', array('class' => 'form-control', 'required' => true)); ?> </div> <div class="form-group"> <label class="required">Senha:</label> <?php echo $this->Form->input('password', array('class' => 'form-control', 'required' => true)); ?> </div> <div class="form-group"> <label class="required">Organização:</label> <?php echo $this->Form->input('organizacao_id', array('class' => 'form-control', 'required' => true));?> </div> <div class="form-group"> <label class="required">Perfil:</label> <?php echo $this->Form->input('perfil_id', array('class' => 'form-control', 'required' => true)); ?> </div> <div class="form-group"> <label class="required">Cargo:</label> <?php echo $this->Form->input('cargo_id', array('id'=>'cargoID', 'type'=>'select'/*echo $this->Form->input('cargo_id', array('class' => 'form-control', 'required' => true*/)); /*echo '<div id="loading" style="display: none"><b>' . $this->Html->image('carregando.gif') . ' Aguarde, carregando cidades...</b></div>'; echo $this->Form->input('classe_id', array('type' => 'select', 'class' => 'form-control_cargo', 'required' => true, 'empty'=>'Selecione a classe do usuário'));*/ ?> </div> <div class="form-group"> <label class="required">Classe:</label> <?php echo $this->Form->input('classe_id', array('id' => 'classeId', 'type' => 'select', 'class' => 'form-control_cargo', 'required' => true, 'empty'=>'Selecione a classe do usuário')); ?> </div> <?php $options = array( 'url' => array('controller' => 'classes' , 'action' => 'buscaClasses'), // Action a ser chamado 'update' => 'classeID', // ID do elemento a se atualizar ); echo $ajax->observeField('cargoID' , $options)?> // Observamos o elemento com ID "cargoID" <div class="form-group"> <label class="required">Função:</label> <?php echo $this->Form->input('funcao_id', array('class' => 'form-control', 'required' => true)); ?> </div> </fieldset> <p class="pull-left"> <?php echo $this->Form->button('Salvar', array('type' => 'submit', 'class' => 'btn btn-success')); ?> <?php echo $this->Html->link('Cancelar', array('action' => 'index'), array('class' => 'btn btn-danger')); ?> </p> </p> <?php echo $this->Form->end(); ?> </div> <?php echo $this->Ajax->observeField('UsuarioCargo', array( 'url' => array( 'action' => 'listar_classes' ), 'frequency' => 0.2, 'update' => 'UsuarioClasse', 'indicator' => 'loading', ) ); ?> </div> ele esta mostrando variavel indefinida para $javascript. Meu controller: ClassesController: <?php App::uses('AppController', 'Controller'); /** * Classes Controller * * @property Classe $Classe * @property PaginatorComponent $Paginator */ class ClassesController extends AppController { /** * Components * * @var array */ public $components = array('Paginator'); var $helpers = array('Html', 'Form','Javascript','Ajax'); var $uses = array('Cargo','Classe'); /** * index method * * @return void */ public function index() { $order = array('Classe.sort'=>'ASC'); $this->paginate = array( 'limit'=>10, 'recursive'=>0, 'fields'=>array( 'Classe.*', ), 'order'=>$order, ); $this->Classe->recursive = 0; $this->set('classes', $this->Paginator->paginate()); } /** * view method * * @throws NotFoundException * @param string $id * @return void */ public function view($id = null) { if (!$this->Classe->exists($id)) { throw new NotFoundException(__('Invalid classe')); } $classes = $this->Classe->find('first', array('conditions' => array('Classe.' . $this->Classe->primaryKey => $id))); /*$classes['UsuarioAvaliacao'] = $this->Classe->UsuarioAvaliacao->find('all', array('conditions' => array('UsuarioAvaliacao.classe_id'=>$id)));*/ $this->set('classe', $classes); $this->set('modal_title', __('CLASSE - ') .'<b>'.$classes['Classe']['nome'].'</b>'); $this->layout = 'modal'; /*$avaliacoes = $this->Classe->UsuarioAvaliacao->find('all', array('conditions' => array('UsuarioAvaliacao.classe_id'=>$classes['UsuarioAvaliacao']['classe_id'])));*/ /*$classes = $this->Classe->find('first', array('recursive'=>0,'conditions' => array('Classe.' . $this->Classe->primaryKey => $id))); $classes['UsuarioAvaliacao'] = $this->Classe->UsuarioAvaliacao->find('all', array('conditions' => array('UsuarioAvaliacao.classe_id'=>$id)));*/ } /** * add method * * @return void */ public function add() { if ($this->request->is('post')) { $this->Classe->create(); if ($this->Classe->save($this->request->data)) { $this->Session->setFlash(__('The classe has been saved.')); return $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The classe could not be saved. Please, try again.')); } } $cargos = $this->Classe->Cargo->find('list'); $this->set(compact('cargos')); } /** * edit method * * @throws NotFoundException * @param string $id * @return void */ public function edit($id = null) { if (!$this->Classe->exists($id)) { throw new NotFoundException(__('Invalid classe')); } if ($this->request->is(array('post', 'put'))) { if ($this->Classe->save($this->request->data)) { $this->Session->setFlash(__('The classe has been saved.')); return $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The classe could not be saved. Please, try again.')); } } else { $options = array('conditions' => array('Classe.' . $this->Classe->primaryKey => $id)); $this->request->data = $this->Classe->find('first', $options); } $cargos = $this->Classe->Cargo->find('list'); $this->set(compact('cargos')); } /** * delete method * * @throws NotFoundException * @param string $id * @return void */ public function delete($id = null) { $this->Classe->id = $id; if (!$this->Classe->exists()) { throw new NotFoundException(__('Invalid classe')); } $this->request->allowMethod('post', 'delete'); if ($this->Classe->delete()) { $this->Session->setFlash(__('The classe has been deleted.')); } else { $this->Session->setFlash(__('The classe could not be deleted. Please, try again.')); } return $this->redirect(array('action' => 'index')); } function buscaClasses() { $this->layout = 'ajax'; // Utilizamos layout ajax $cargoID = $this->data['Cargo']['cargo']; // Pegamos o id da categorias selecionada $classes = $this->Classe->find('list' , array('conditions' => array('Classe.cargo_id' => $cargoID))); // Encontramos todas as subcategorias que pertencem a $catID foreach($classes as $key => $classe){ // Iteramos, e devolvemos os options do selectbox echo "<option value=\"{$key}\">{$classe}</option>"; } } } Ele ta me passando o seguinte erro: Error: AjaxHelper could not be found. Error: Create the class AjaxHelper below in file: fgv\View\Helper\AjaxHelper.php Sou novo em programacao e me falta muito mas to suando a mente(rsrs), pra aprender, se puderes me ajudar agradeco! Compartilhar este post Link para o post Compartilhar em outros sites