[Resolvido] Preenchimento automático do formulário.

E ai galera, sou novo no Yii e estou com uma dúvida aqui.

Gostaria de preencher um campo do meu form usando os dados que tem no meu banco, sendo que ele está em um dropDownList.

O que eu quero é mais ou menos assim, quando eu escolher a categoria(que é a dropDownList) ele preencha automaticamente o campo "Diária" do meu form com o valor "diária" que está dentro na tabela Categorias.




        // Aqui está o dropDownList. Assim que eu escolher a categoria

        <div class="row">

		<?php echo $form->labelEx($model,'categoria'); ?>

		<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

                      echo $form->dropDownList($model,'categoria',$data, array('empty'=>'Categoria')); ?>

		<?php echo $form->error($model,'categoria'); ?>

	</div>

                

        // ele preencha o textField da diária com o valor correspondente a categoria

	<div class="row">

		<?php echo $form->labelEx($model,'diaria'); ?>

		<?php echo $form->textField($model,'diaria',array('size'=>10,'maxlength'=>10)); ?>

		<?php echo $form->error($model,'diaria'); ?>

	</div>




Att.

Faça uma chamada Ajax a partir do seu dropdown e atualize o valor do campo, mais ou menos assim:




        <div class="row">

                <?php echo $form->labelEx($model,'categoria'); ?>

                <?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 


                      echo $form->dropDownList($model,'categoria',$data, array('empty'=>'Categoria'),array(


                          'ajax'=>  array(

                                          'type'=>'POST',

                                          'dataType'=>'json',

                                          'url'=>CController::createUrl('categorias/getValorDiaria'),

                                          'update'=>'#NOME_MODEL_DO_FORM[diaria]',


                       )); ?>

                <?php echo $form->error($model,'categoria'); ?>

        </div>



No controller das categorias, retorne algo assim:




	public function actionGetValorDiaria()

        {

          $id_cat = $_POST['NOME_MODEL_DO_FORM']['categoria'];

          $data = Yii::app()->db->createCommand("SELECT diaria FROM <TABELA_CATEGORIAS> WHERE codigo='$id_cat'")->queryRow(false);


          echo CJSON::encode(array('diaria'=>$data[0]));

        }



Este post pode ser muito útil também

http://www.yiiframework.com/wiki/24/creating-a-dependent-dropdown

Espero que ajude

Abraços!

Bom vamos por parte para ver se entendi direito.

Este é o nome do meu form certo?




<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'apartamento-form', // <---- AQUI

	'enableAjaxValidation'=>false,

)); ?>



Pelo que li no link que você me enviou, diz que eu tenho que usar o Controller atual para fazer o "update".

Mais não surte efeito nem no Controller atual (ApartamentoController, que é onde estou usando o _form) nem do Controller da Categoria(CategoriaApController).

Tudo ficou assim:

_form.php




<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'apartamento-form',

	'enableAjaxValidation'=>false,

)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'numero'); ?>

		<?php echo $form->textField($model,'numero'); ?>

		<?php echo $form->error($model,'numero'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'categoria'); ?>

		<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

              echo $form->dropDownList($model,'categoria',$data, array('empty'=>'Categoria'),array(

                                        

                                        'ajax'=>array(

                                                      'type'=>'POST',

                                                      'dataType'=>'json',

                                                      'url'=>CController::createUrl('apartamento/getValorDiaria'),

                                                      'update'=>'#apartamento-form[diaria]',

                                        ))); ?>

		<?php echo $form->error($model,'categoria'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'diaria'); ?>

		<?php echo $form->textField($model,'diaria',array('size'=>10,'maxlength'=>10)); ?>

		<?php echo $form->error($model,'diaria'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'no_pax'); ?>

		<?php echo $form->textField($model,'no_pax'); ?>

		<?php echo $form->error($model,'no_pax'); ?>

	</div>


	<div class="row buttons">

		<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>

	</div>


<?php $this->endWidget(); ?>


</div><!-- form -->



ApartamentoController.php




public function actionGetValorDiaria()

    {

        $idcat = $_POST['#apartamento-form']['categoria'];

        $data = Yii::app()->db->createCommand("SELECT diaria FROM categoria_ap WHERE codigo='$idcat'")->queryRow(false);

        

        echo CJSON::encode(array('diaria'=>$data[0]));

    }



O que estou fazendo de errado?

Laverson,

Faltou você enviar o ID do item selecionado no dropDown.

Olha o modelo do meu:




echo $form->dropDownList($model, 'uf', $estados, array(

            'prompt' => 'Selecione',

            'ajax' => array(

                'type' => 'POST', //request type

                'url' => Yii::app()->createUrl('uf/municipios'), //url to call.

                'update' => 'select[id=codmunicipio]', //selector to update

                'data' => array('uf' => 'js:$(this).val()')

            ),

        ));



Usa o firebug tanto do Firefox ou Chrome, e veja se as requisições em ajax estão enviando e recebendo os dados correto.

Ao que parece, esta linha aqui está incorreta




$idcat = $_POST['#apartamento-form']['categoria'];  //remover o sustenido #



A dica do Newerton também é muito válida, verifique o que está sendo enviado pelo POST. No controller, faça um var_dump($_POST) ou print_r($_POST) e verifique o que você recebe no valor do parâmetro que será usado de filtro.

Abraços!

Newerton,

tentei fazer do seu jeito mais ainda não tive sucesso, o meu código ficou assim:




<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

              echo $form->dropDownList($model,'categoria',$data, array('empty'=>'Categoria',

                                        

                                        'ajax'=>array(

                                                      'type'=>'POST',

                                                      //'dataType'=>'json', <-- comentei isto para

                                                      'url'=>Yii::app()->createUrl('apartamento/getValorDiaria'),

                                                      'update'=>'#apartamento-form[diaria]',

                                                      'data'=>array('categoria'=>'js:$(this).val()'),

                                                )

                                       )); 

        ?>



esta parte do seu código não entendi direito




...

   'update' => 'select[id=codmunicipio]', //selector to update

   'data' => array('uf' => 'js:$(this).val()')

...



Outra coisa, quanto ao link que o scoob.junior forneceu la tem dizendo que funciona em duas dropDownList’s no meu caso é uma dropDownList (de onde eu quero pegar a diária) e um textField (onde eu quero jogar o valor da diária) que está no mesmo form. Tem algum problema quanto a isso?

Usei o var_dump($_POST) e o print_r($_POST) como sugerido, nada me foi retornado. <_<

Eu tenho que "importar" o json na minha app?

Posso estar enganado mais acho que ele não está chamando o actionGetValorDiaria, pois mudei o $idcat por um valor default (1) e nada aconteceu também.

Ps. Não sei usar o firebug. :(

Laverson,

Primeiro verifica se foi criado no Controller(ApartamentoController) o action (actionGetValorDiaria).

Se estiver criado no actionGetValorDiaria faz assim como teste:




public function actionGetValorDiaria(){

echo '<option>OK</option>';

}



Isso já deve funcionar os nosso testes de retorno.

Agora vamos tratar o retorno e a atualização do outro dropDown.

Sobre sua dúvida no:




'update' => 'select[id=codmunicipio]', //selector to update

'data' => array('uf' => 'js:$(this).val()')



O ‘update’ e onde eu desejo atualizar quando os dados for retornado por ajax.

O ‘data’ e a variavel que deseja enviar, como eu estava usando Estado -> Municipio, eu enviei ‘uf’ para me retornar todos os municipio daquele estado.

Somente verifica no seu ‘update’:




'update'=>'#apartamento-form[diaria]',



E para você atualizar o ‘select’ e não o formulário, talvez no ‘update’ tu muda assim:




'update'=>'select#Apartamento_diaria',



Faça o teste se tu funcionar e retornar o OK no select ai sim tu muda seu actionGetValorDiaria que está incorreto o retorno dos dados.

Faça nesse modelo que usei para pegar todos os municípios de um UF:




public function actionMunicipios() {


        $municipios = Municipio::model()->findAll(array(

			'condition' => 'uf = :uf',

			'params' => array(

				':uf' => $_POST['ud']

			),

			'order' => 'municipio ASC'

		));

        $municipios = CHtml::listData($municipios, 'codmunicipio', 'municipio');


        echo CHtml::tag('option', array('value' => ''), CHtml::encode('Selecione'), true);

        foreach ($municipios as $value => $name) {

            echo CHtml::tag('option', array('value' => $value), CHtml::encode($name), true);

        }

    }



Newerton,

o action foi criado, porém, ontem, percebi que realmente a chamada para o action (actionGetValorDiaria) não estava sendo feita.

Mudei disso:




...

'url'=>CController::createUrl('apartamento/getValorDiaria'),

...



para isso:




...

'url'=>CController::createUrl(Yii::app()->Controller->actionGetValorDiaria()),

...



e funcionou. Com a restrição de só ser chamado quando o form é enviado.

O meu problema é o seguinte, quando escolho a categoria ele nem se quer chama o actionGetValorDiaria, consegui pegar os valores do $_POST (como sugerido pelo scoob.junior vlw scoob :) ) com a função var_dump($_POST) após a mudança dita acima, mais ele só chama esse action quando eu envio o formulário, ou seja, clico no “botão submit”. Isso está certo?

Outra coisa, não quero atualizar um "select" e sim um campo textField.

i.e.: Quando eu escolher uma categoria (que é um dropDownList) ele preencha automaticamente o campo "diaria" do mesmo form (que é um textField) mais sem precisar enviar o formulário.

Algumas dúvidas estão nos comments.

Aqui está meu form




<div class="form">


<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'apartamento-form',  // Este é o nome do form que tenho que usar pra atualizar um campo?

	'enableAjaxValidation'=>true,

)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'numero'); ?>

		<?php echo $form->textField($model,'numero'); ?>

		<?php echo $form->error($model,'numero'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'categoria'); ?>

		<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

              echo $form->dropDownList($model,'categoria',$data, array(

                                        'empty'=>'Categoria',

                                        'ajax'=>array(

                                                      'type'=>'post',

                                                      'dataType'=>'json',

                                                      'url'=>CController::createUrl(Yii::app()->Controller->actionGetValorDiaria()),//'apartamento/getValorDiaria'),

                                                      'update'=>'#apartamento-form[diaria]', // Isto daqui está realmente correto para atualizar o campo diaria?

                                                      'data'=>array('categoria'=>'js:$(this).val()')// Mesmo sem isso o valor do id da categoria está sendo enviado, mais o preservei assim mesmo

                                        ),

                          )); 

        ?>

		<?php echo $form->error($model,'categoria'); ?>

	</div>


        // Quero que o valor da diária que está no dropDownList acima venha para o campo abaixo

	<div class="row">

		<?php echo $form->labelEx($model,'diaria'); ?>

		<?php echo $form->textField($model,'diaria',array('size'=>10,'maxlength'=>10));?>

		<?php echo $form->error($model,'diaria'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'no_pax'); ?>

		<?php echo $form->textField($model,'no_pax'); ?>

		<?php echo $form->error($model,'no_pax'); ?>

	</div>


	<div class="row buttons">

		<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>

	</div>


<?php $this->endWidget(); ?>


</div><!-- form -->



Este é meu action




public function actionGetValorDiaria()

    {

            print_r($_POST);

            $idcat = $_POST['Apartamento']['categoria'];


            $data = Yii::app()->db->createCommand()

                                           ->select('diaria')

                                           ->from('categoria_ap')

                                           ->where('codigo=:id', array(':id'=>$idcat))

                                           ->queryRow(false); 

            echo CJSON::encode(array('diaria'=>$data[0]));

    }



Tentei usar CHtml::tag como sugerido por você, mais ele criou um novo campo.

Ps.: Se eu não estiver sendo muito claro desculpe. :)

Se você observar o código fonte HTML gerado, perceba que o ID dos atributos na tela não é simplesmente o nome do form seguido de [attname] (#apartamento-form[diaria]), mas sim o model seguido de underline seguido do nome do atributo, algo do tipo assim:




<input id="Apartamento_diaria" name="Apartamento[diaria]" />



Verifique isso seja com firebug ou com o inspetor de html do seu browser.

Para simplificar, veja o link do nosso projetinho Yiiplayground que tem alguns exemplos prontos e funcionando sobre chamadas ajax e atualização de valores na página:

http://yiiplayground.cubedwater.com

mais especificamente em

http://www.yiiplayground.cubedwater.com/index.php?r=AjaxModule/ajax/ajaxRequest

:)

Abraços!!

isso ajudaria …?




<?php 

echo $form->textArea($model, "campo", array(

                                            'name'  => CHtml::activeName($model, 'campo[]'), 

                                            'style' => 'width: 570px; height: 80px;'));

?>



eu esta com problema mas no textArea …

e isso resolveu.




'name'  => CHtml::activeName($model, 'campo[]')



E ai pessoal, primeiramente gostaria de agradecer a todos por tentar me ajudar.

radames_, o que você sugeriu foi o que mais chegou perto, consegui por um valor dentro do textField mais o valor era da forma “Apartamento[<campo>]”. Vlw pela ajuda. :)

scoob.junior, obrigado por ter esclarecido minha dúvida quanto ao nome do form, que era Apartamento (assim como mensionado pelo Newerton,vlw cara :) , e passado desapercebido por mim <_< ). Agora as coisas estão bem mais claras. :D

Como eu disse no reply #6, “…quanto ao link que o scoob.junior forneceu la tem dizendo que funciona em duas dropDownList’s…”, funcionou aqui depois que eu substituí o textField por um droDownList.

Meu _form agora:




<div class="row">

	<?php echo $form->labelEx($model,'categoria'); ?>

	<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

          echo $form->dropDownList($model,'categoria',$data, array(

                                    'empty'=>'Categoria',

                                    'ajax'=>array(

                                              'type'=>'POST',

                                              'url'=>CController::createUrl('apartamento/getValorDiaria'),

                                              'update'=>'#Apartamento_diaria',

                                    ),

                      )); 

    ?>

</div>


<div class="row">

	<?php echo $form->labelEx($model,'diaria'); ?>

	<?php echo $form->dropDownList($model,'diaria',array());//, 'value'=>CHtml::activeName($model,'diaria[]')));?>

</div>



Meu Controller:




public function actionGetValorDiaria()

{

        $idcat = $_POST['Apartamento']['categoria'];

        //$data = Yii::app()->db->createCommand("SELECT diaria FROM categoria_ap WHERE codigo='$idcat'")->queryRow(false);

        $data = Yii::app()->db->createCommand()

                              ->select('diaria')

                              ->from('categoria_ap')

                              ->where('codigo=:id', array(':id'=>$idcat))

                              ->queryRow(false); 

        echo CHtml::tag('option',array('value'=>$data[0]),CHtml::encode($data[0]),true);

}




Agora uma dúvida (mais algumas heheh), este tipo de chamada só vai dar um update em uma outra dropDownList, nenhuma outra tag vai aceitar este tipo de update?

E um erro está a ocorrer, assim que seleciono a categoria ele está salvando o form. =/

Você pode tentar fazer o seguinte, em vez de utilizar o ‘update’, dá uma estudada no callback ‘success’, daí você tem mais liberdade para escrever o código que quiser em jQuery.

Não testei o código abaixo, mas com pequenas modificações deve funcionar

fica algo assim:




<div class="row">

        <?php echo $form->labelEx($model,'categoria'); ?>

        <?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

        <?php echo $form->dropDownList($model,'categoria',$data, array(

                                    'empty'=>'Categoria',


                                    'ajax'=>array(

                                              'type'=>'POST',

                                              'url'=>CController::createUrl('apartamento/getValorDiaria'),

                                              'success'=>"function(data) {

                                                     alert('Valor deve ser: ' + data.diaria);

                                                     $('#Apartamento_diaria').val(data.diaria);  //ou .html() - testar

                                               }"

                                    ),

                      )); 

        ?>

</div>




<div class="row">

        <?php echo $form->labelEx($model,'diaria'); ?>

        <?php echo $form->textField($model,'diaria',array()); ?>

</div>




e no controller





public function actionGetValorDiaria()

{

        $idcat = $_POST['Apartamento']['categoria'];

        //$data = Yii::app()->db->createCommand("SELECT diaria FROM categoria_ap WHERE codigo='$idcat'")->queryRow(false);

        $data = Yii::app()->db->createCommand()

                              ->select('diaria')

                              ->from('categoria_ap')

                              ->where('codigo=:id', array(':id'=>$idcat))

                              ->queryRow(false); 


        echo CJSON::encode(array('diaria'=>$data['diaria']));

}




Abraços

scoob.junior vou dar uma estudada nisso sim, vlw ai.

Por hora como não posso atrasar muito o que estou fazendo, preferi (depois de exaustivas tentativas de fazer o que queria) fazer de outra forma e que deu certo, pegar apenas o valor da diária caso ela tenha sido digitada, se não pego do banco sem nenhum problema.

Mais como alegria de pobre dura pouco, me ocorreu um outro problema ele salva o form assim que escolho a categoria, quando clico em "Create" ele acusa que o item está duplicado. Ele só salva quando eu digito o "Número", se o deixar em branco ele não salva esperando que eu clique em "Create" depois de informar o mesmo.

_form




<div class="row">

	<?php echo $form->labelEx($model,'numero'); ?>

	<?php echo $form->textField($model,'numero'); ?>

</div>


<div class="row">

	<?php echo $form->labelEx($model,'categoria'); ?>

	<?php $data = CHtml::listData(CategoriaAp::model()->findAll(),'codigo','categoria'); 

              echo $form->dropDownList($model,'categoria',$data, array('empty'=>'Categoria')); 

    ?>

</div>


<div class="row">

	<?php echo $form->labelEx($model,'diaria'); ?>

	<?php echo $form->textField($model,'diaria',array('size'=>10,'maxlength'=>10))?>

</div>



Já removi também o action do controller e mesmo assim continua a salvar.

Pelo que entendi, posso estar me equivocando, assim que eu insiro o "Número" e escolho a "Categoria" ele já faz uma chamada "ajax" para o actionCreate, dai quando clico no botão "Create" ele acusa a duplicação do item.

Laverson,

Adicionando o dataType, senão o retorno será uma string do CHTML::encode().


...

'type'=>'POST',

'url'=>CController::createUrl('apartamento/getValorDiaria'),

'dataType'=>'json',

'success'=>"function(data) {

           alert('Valor deve ser: ' + data.diaria);

           $('#Apartamento_diaria').val(data.diaria);  //ou .html() - testar

}"

...

Newerton,

o esse ajax só funciona de [b]dropDownList[/b] para [b]dropDownList[/b]?

Posso usar ele de um textField para outro textField?

Dá para você usar o ajax em quaisquer componente.

Porém, na função ‘success’ do ajax, se você for usar textField(AutoComplete) para textField(Normal), você terá que fazer o tratamento.

Se não me engano no retorno dos arquivos do AutoComplete os dados vem concatenado com barras (|) <- simbolo exotico hehe

heheh

Tentei isto, para atualizar o campo ‘subtotal’ automaticamente quando a quantidade (quant) fosse informada, mais não funcionou:

_form:




...

<?php echo $form->textField($model,'quant', array(

                          'ajax'=>array(

                              'type'=>'POST',

                              'url'=>CController::createUrl('itens/calcularSubTotal'),

                              'dataType'=>'json',

                              //'update'=>'#Itens_subtotal', <-- Com isto tembém

                              'success'=>"function(data){

                                              $('#Itens_subtotal').val(data); // E com .html()

                                          }",

                          )

                      )

                  );

?>

...

<div class="row">

		<?php echo $form->labelEx($model,'subtotal'); ?>

		<?php echo $form->textField($model,'subtotal',array('disabled'=>true));?> 

</div>



Controller:




public function actionCalcularSubTotal()

{

    $prod = $_POST['Itens']['fkProduto'];

    $quant = $_POST['Itens']['quant'];

    $data = Yii::app()->db->createCommand("SELECT preco FROM produto WHERE codigo='$prod'")->queryRow(false);

    

    $subtotal = $data[0]*$quant;

    

    /**

     * echo CHtml::tag('input', array('type'=>'text', 'value'=>$subtotal, 'id'=>'Itens_subtotal'));

     * Yii::app()->end();    <--- Tentei com isso...

     */

    

    //echo CJSON::encode($subtotal); <--- E com isso aqui também...

    

    /**

     * echo CJSON::encode(array('subtotal'=>$subtotal)); <--- e mais isso...

     * Yii::app()->end();

     * */

    

    echo CHtml::tag('input',array('value'=>$data[0]),CHtml::encode($data[0]),true); // <-- por fim isso

}



Você teria algum exemplo que eu possa estudar?

Laverson,

Veja se os modelos abaixo vai funcionar

_form




<?php echo $form->textField($model,'quant'); ?>

...

<div class="row">

                <?php echo $form->labelEx($model,'subtotal'); ?>

                <?php echo $form->textField($model,'subtotal',array('disabled'=>true));?> 

</div>



Antes do $this->beginWidget(‘CActiveForm’), você adiciona:




Yii::app()->clientScript->registerScript('produto', "


jQuery('input[id=Itens_quant]').live('blur', function(){


	jQuery.ajax({

		'type':'POST',

		'url':'".Yii::app()->createUrl('itens/calcularsubtotal')."',

		'success':function(data){

			$('#Itens_subtotal').val(data);

		},

		'data':{

			'quant':$(this).val(),

			'codigo': '".$model->codigo."'

		},

		'cache':false

	});


});




");



Controller:


public function actionCalcularSubTotal()

{

    $prod = $_POST['codigo'];

    $quant = $_POST['quant'];

	$data = Produto::model()->find(array(

				'condition' => 'codigo = :codigo',

				'params' => array(

					':codigo' => $prod

				)

			));

    

    $subtotal = $data->preco * $quant;

    

    echo $subtotal

}

Newerton,

deu certo finalmente. Muito obrigado cara. Algumas dúvidas que eu tinha foram esclarecidas e agora está funcionando.

Mas como tudo na vida não são flores, tive que tirar o $_POST[‘codigo’] e por um valor constante de uma PK de um Produto.

Tenho um textField, no mesmo form, que possui este valor porém não consegui obtê-lo.

Tentei fazer assim:

Controller:




$prod = 1; <---- Assim deu certo


...


$prod = $_POST['fkProduto']; <---- Assim não deu



Este fkProduto é a chave estrangeira do produto no qual eu devo pegar o preço e calcular o subtotal com a quantidade.