Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

lucaswxp

[TUTORIAL] AJAX com CakePHP - parte 2

Recommended Posts

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

Esta colaborando bem aqui em cake

Compartilhar este post


Link para o post
Compartilhar em outros sites

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

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

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.