Yii Dropdown Onchange


<?php

            echo 'Account Type:  ';

            echo $form->dropDownList($account, 'AccountTypeName', $AccountType->getAccounttype(), array('prompt' => '','style'=>'width:150px;'));

            echo 'Status:  ';

            echo $form->dropDownList($account, 'Status', array('1' => 'Active', '2' => 'Locked by Admin', '3' => 'Locked by Attempt', '4' => 'Expired'), array('prompt' => '','style'=>'width:150px;'));

            ?></br> 

            <?php echo 'Advanced Search:  Username:  ';

            echo $form->dropDownList($account, 'UzerName', $AccountType->getUserName(), array('prompt' => '','style'=>'width:150px;'));

            ?>

I have this 3 dropdown fields and I want to do is when I choose a value on Username dropdown the two other dropdowns will be empty just like a normal javascript with onchange function, how can I do than on yii?

Try this:

http://www.yiiframework.com/wiki/24/

you can write required js function and call them on onchange event of each dropdown.

I tried this one :


<?php

            echo 'Account Type:  ';

            echo $form->dropDownList($account, 'AccountTypeName', $AccountType->getAccounttype(), array('prompt' => '','style'=>'width:150px;'));

            echo 'Status:  ';

            echo $form->dropDownList($account, 'Status', array('1' => 'Active', '2' => 'Locked by Admin', '3' => 'Locked by Attempt', '4' => 'Expired'), array('prompt' => '','style'=>'width:150px;'));

            ?></br> 

            <?php echo 'Advanced Search:  Username:  ';

            echo $form->dropDownList($account, 'UzerName', $AccountType->getUserName(), array( 'onChange' => 'javascript:emptyfields()' ), array('prompt' => '','style'=>'width:150px;'));

            ?>


<script type="text/javascript">

    function emptyfields()

    {

        document.getElementById('Status').value="";

        document.getElementById('AccountTypeName').value="";

    }

    </script>




but still it didnt work…

use dependent dropdowns .

try the link, Fabrizio Caldarelli replied.

http://www.yiiframework.com/wiki/24/

sory to interrupt here, because this thread has similiar problem with my thread here

while my code work fine with dependent dropdowns base on http://www.yiiframework.com/wiki/24/ example, but i can not save the data into database. can anyone tell me what im missing in my code?




        <?php 

                $topic=new Topic();


               //TOPIC NOT NEED TO BE SAVED TO DATABASE

                echo $form->labelEx($topic,'topic_id');

                echo CHtml::dropDownList('topic_id','',Topic::getTopics(''),

                    array(

                        'prompt'=>'-- select topic --',

                        'ajax' => 

                            array(

                                'type'=>'POST', 

                                'url'=>CController::createUrl('skn/Blog/GetCategoryByTopic'),

                                'update'=>'#category_id', 

                            )

                    )

                );


                echo $form->error($topic,'topic_id');


                //CATEGORY MUST BE SAVED, BUT RETURN NULL VALUE TO DATABASE

                echo $form->labelEx($model,'category');

                echo CHtml::dropDownList('category_id',$model, array(),array('empty' => '-- select topic --'));

                echo $form->error($model,'category_id');                

                

        ?>  



Please post model code to save form data.

the model is Blog model. i put the code below. it has a base class, generated using Giix module.

i just wonder, is that happen (can not save/return null) because i use "echo CHtml::dropDownList" instead of "echo $form->dropDownList"? if i use "echo $form->dropDownList" for dependent dropdown, i get a PHP Warning, but "echo CHtml::dropDownList" works fine, but it return null and i cannot save it.

Blog.php

//base blog code below blog.php


<?php


Yii::import('application.models.skn._base.BaseBlog');


class Blog extends BaseBlog

{

        private $_oldTags;

        

	public static function model($className=__CLASS__) {

		return parent::model($className);

	}

        


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('title, content, blog_status', 'required'),

			//array('blog_status', 'in', 'range'=>array(1,2,3,4)),

			array('title', 'length', 'max'=>128),

			array('tags', 'match', 'pattern'=>'/^[\w\s,]+$/', 'message'=>'Tags can only contain word characters.'),

			array('tags', 'normalizeTags'),


			array('title, status', 'safe', 'on'=>'search'),

		);

	}        

        

	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'author' => array(self::BELONGS_TO, 'User', ObjectSender::getColumnAuthorId()),

			'comments' => array(self::HAS_MANY, 'Comment', ObjectSender::getColumnBlogId(), 

                                                'condition'=>'comments.comment_status='.ObjectSender::getStatusApproved(), 

                                                'order'=>'comments.create_time DESC'),

			'commentCount' => array(self::STAT, 'Comment', ObjectSender::getColumnBlogId(), 

                                                'condition'=>ObjectSender::getColumnCommentStatus().'='.ObjectSender::getStatusApproved()),

		);

	}    

        

	/**

	 * @return string the URL that shows the detail of the blog

	 */

	public function getUrl()

	{

		return Yii::app()->createUrl('skn/blog/view', array(

			'id'=>$this->blog_id,

			'title'=>$this->title,

		));

	}        

        

	/**

	 * @return array a list of links that point to the blog list filtered by every tag of this blog

	 */

	public function getTagLinks()

	{

		$links=array();

		foreach(Tag::string2array($this->tags) as $tag)

			$links[]=CHtml::link(CHtml::encode($tag), array('skn/blog/index', 'tag'=>$tag));

		return $links;

	}        

        

	/**

	 * Normalizes the user-entered tags.

	 */

	public function normalizeTags($attribute,$params)

	{

		$this->tags=Tag::array2string(array_unique(Tag::string2array($this->tags)));

	}


	/**

	 * Adds a new comment to this blog.

	 * This method will set status and blog_id of the comment accordingly.

	 * @param Comment the comment to be added

	 * @return boolean whether the comment is saved successfully

	 */

	public function addComment($comment)

	{

                $comment_status=ObjectSender::getColumnCommentStatus();

                $blog_id=ObjectSender::getColumnBlogId();

                

		//if(Yii::app()->params['commentNeedApproval'])

                

                $commentApproval = ObjectSender::getCommentApproval();

                if(Yii::app()->$commentApproval)

			$comment->$comment_status=ObjectSender::getStatusPending ();

		else

			$comment->$comment_status=ObjectSender::getStatusApproved();

		$comment->$blog_id=$this->$blog_id;

		return $comment->save();

	}


	/**

	 * This is invoked when a record is populated with data from a find() call.

	 */

	protected function afterFind()

	{

		parent::afterFind();

		$this->_oldTags=$this->tags;

	}


	/**

	 * This is invoked before the record is saved.

	 * @return boolean whether the record should be saved.

	 */

	protected function beforeSave()

	{

		if(parent::beforeSave())

		{

			if($this->isNewRecord)

			{

				$this->create_time=$this->update_time=time();

				$this->author_id=Yii::app()->user->id;

			}

			else

				$this->update_time=time();

			return true;

		}

		else

			return false;

	}


	/**

	 * This is invoked after the record is saved.

	 */

	protected function afterSave()

	{

		parent::afterSave();

		Tag::model()->updateFrequency($this->_oldTags, $this->tags);

	}


	/**

	 * This is invoked after the record is deleted.

	 */

	protected function afterDelete()

	{

            

		parent::afterDelete();

		Comment::model()->deleteAll('blog_id='.$this->blog_id);

		Tag::model()->updateFrequency($this->tags, '');

	}

        

	/**

	 * Retrieves the list of blogs based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the needed blogs.

	 */

	public function search()

	{

                $blog_status=ObjectSender::getColumnBlogStatus();

		$criteria=new CDbCriteria;


		$criteria->compare('title',$this->title,true);


		$criteria->compare($blog_status,$this->blog_status);


		return new CActiveDataProvider('Blog', array(

			'criteria'=>$criteria,

			'sort'=>array(

				'defaultOrder'=> $blog_status.', update_time DESC',

			),

		));

	}                

}

BaseBlog.php


<?php


/**

 * This is the model base class for the table "{{blog}}".

 * DO NOT MODIFY THIS FILE! It is automatically generated by giix.

 * If any changes are necessary, you must set or override the required

 * property or method in class "Blog".

 *

 * Columns in table "{{blog}}" available as properties of the model,

 * followed by relations of table "{{blog}}" available as properties of the model.

 *

 * @property integer $blog_id

 * @property integer $category_id

 * @property string $title

 * @property string $content

 * @property string $tags

 * @property integer $blog_status

 * @property integer $create_time

 * @property integer $update_time

 * @property integer $author_id

 *

 * @property User $author

 * @property Category $category

 * @property PostStatus $blogStatus

 * @property Comment[] $comments

 */

abstract class BaseBlog extends GxActiveRecord {


	public static function model($className=__CLASS__) {

		return parent::model($className);

	}


	public function tableName() {

		return '{{blog}}';

	}


	public static function label($n = 1) {

		return Yii::t('app', 'Blog|Blogs', $n);

	}


	public static function representingColumn() {

		return 'title';

	}


	public function rules() {

		return array(

			array('category_id, title, content, blog_status, author_id', 'required'),

			array('category_id, blog_status, create_time, update_time, author_id', 'numerical', 'integerOnly'=>true),

			array('title', 'length', 'max'=>128),

			array('tags', 'safe'),

			array('tags, create_time, update_time', 'default', 'setOnEmpty' => true, 'value' => null),

			array('blog_id, category_id, title, content, tags, blog_status, create_time, update_time, author_id', 'safe', 'on'=>'search'),

		);

	}


	public function relations() {

		return array(

			'author' => array(self::BELONGS_TO, 'User', 'author_id'),

			'category' => array(self::BELONGS_TO, 'Category', 'category_id'),

			'blogStatus' => array(self::BELONGS_TO, 'PostStatus', 'blog_status'),

			'comments' => array(self::HAS_MANY, 'Comment', 'blog_id'),

		);

	}


	public function pivotModels() {

		return array(

		);

	}


	public function attributeLabels() {

		return array(

			'blog_id' => Yii::t('app', 'Blog'),

			'category_id' => null,

			'title' => Yii::t('app', 'Title'),

			'content' => Yii::t('app', 'Content'),

			'tags' => Yii::t('app', 'Tags'),

			'blog_status' => null,

			'create_time' => Yii::t('app', 'Create Time'),

			'update_time' => Yii::t('app', 'Update Time'),

			'author_id' => null,

			'author' => null,

			'category' => null,

			'blogStatus' => null,

			'comments' => null,

		);

	}


	public function search() {

		$criteria = new CDbCriteria;


		$criteria->compare('blog_id', $this->blog_id);

		$criteria->compare('category_id', $this->category_id);

		$criteria->compare('title', $this->title, true);

		$criteria->compare('content', $this->content, true);

		$criteria->compare('tags', $this->tags, true);

		$criteria->compare('blog_status', $this->blog_status);

		$criteria->compare('create_time', $this->create_time);

		$criteria->compare('update_time', $this->update_time);

		$criteria->compare('author_id', $this->author_id);


		return new CActiveDataProvider($this, array(

			'criteria' => $criteria,

		));

	}

}

I need also action method of controller called when submit form.

BlogController.php


<?php


class BlogController extends GxController {


	/**

	 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning

	 * using two-column layout. See 'protected/views/layouts/column2.php'.

	 */

	public $layout='//layouts/column2';    

    

        public function filters() {

                return array(

                                'accessControl', 

                                );

        }


        public function accessRules() {

                return array(

                                array('allow',

                                        'actions'=>array('index','view'),

                                        'roles'=>array('*'),

                                        ),

                                array('allow', 

                                        'actions'=>array('minicreate', 'create','update','GetCategoryByTopic'),

                                        'roles'=>array('UserCreator'),

                                        ),

                                array('allow', 

                                        'actions'=>array('admin','delete'),

                                        'users'=>array('admin'),

                                        ),

                                array('deny', 

                                        'users'=>array('*'),

                                        ),

                                );

        }


	public function actionView($id) {

//		$this->render('view', array(

//			'model' => $this->loadModel($id, 'Blog'),

//		));

            

                $blog=$this->loadModel($id);

                $comment=$this->newComment($blog);

                

		$this->render('view',array(

			'model'=>$blog,

                        'comment'=>$comment,

		));            

	}


	public function actionCreate() {

		$model = new Blog;




		if (isset($_POST['Blog'])) {

			$model->setAttributes($_POST['Blog']);


			if ($model->save()) {

				if (Yii::app()->getRequest()->getIsAjaxRequest())

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

				else

					$this->redirect(array('view', 'id' => $model->blog_id));

			}

		}


		$this->render('create', array( 'model' => $model));

	}


	public function actionUpdate($id) {

		$model = $this->loadModel($id, 'Blog');




		if (isset($_POST['Blog'])) {

			$model->setAttributes($_POST['Blog']);


			if ($model->save()) {

				$this->redirect(array('view', 'id' => $model->blog_id));

			}

		}


		$this->render('update', array(

				'model' => $model,

				));

	}


	public function actionDelete($id) {

		if (Yii::app()->getRequest()->getIsPostRequest()) {

			$this->loadModel($id, 'Blog')->delete();


			if (!Yii::app()->getRequest()->getIsAjaxRequest())

				$this->redirect(array('admin'));

		} else

			throw new CHttpException(400, Yii::t('app', 'Your request is invalid.'));

	}


	public function actionIndex() {

//		$dataProvider = new CActiveDataProvider('Blog');

//		$this->render('index', array(

//			'dataProvider' => $dataProvider,

//		));

            

                $blog_status=ObjectSender::getColumnBlogStatus();

                $update_time=ObjectSender::getColumnUpdateTime();

                

                $criteria=new CDbCriteria(array(

                    'condition'=>$blog_status.'='.ObjectSender::getStatusPublished(),

                    'order'=>$update_time.' DESC',

                    'with'=>'commentCount',

                ));

                

                if(isset($_GET['tag']))

                    $criteria->addSearchCondition('tags',$_GET['tag']);


                $dataProvider=new CActiveDataProvider('Blog', array(

                    'pagination'=>array(

                        'pageSize'=>ObjectSender::getPostPerPage(),

                    ),

                    'criteria'=>$criteria,

                ));

                

                $this->render('index',array(

                    'dataProvider'=>$dataProvider,

                ));                

	}


	public function actionAdmin() {

		$model = new Blog('search');

		$model->unsetAttributes();


		if (isset($_GET['Blog']))

			$model->setAttributes($_GET['Blog']);


		$this->render('admin', array(

			'model' => $model,

		));

	}

        

	/**

	 * Suggests tags based on the current user input.

	 * This is called via AJAX when the user is entering the tags input.

	 */

	public function actionSuggestTags()

	{

		if(isset($_GET['q']) && ($keyword=trim($_GET['q']))!=='')

		{

			$tags=Tag::model()->suggestTags($keyword);

			if($tags!==array())

				echo implode("\n",$tags);

                            

		}

	}               

        

	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 * @param integer the ID of the model to be loaded

	 */

	public function loadModel($id)

	{

		$model=Blog::model()->findByPk($id);

		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='blog-form')

		{

			echo CActiveForm::validate($model);

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

		}

	}

        

        protected function newComment($blog)

        {

            $comment=new Comment;

            if(isset($_POST['Comment']))

            {

                $comment->attributes=$_POST['Comment'];

                if($blog->addComment($comment))

                {

                    if($comment->comment_status==ObjectSender::getStatusPending())

                        Yii::app()->user->setFlash('commentSubmitted','Thank you for your comment. Your comment will be bloged once it is approved.');

                    $this->refresh();

                }

            }

            return $comment;

        }            


        

        public function actionGetCategoryByTopic()

        {

  	   $data=Category::model()->findAll('topic_id=:topic_id',

                    array(':topic_id'=>(int) $_POST['topic_id']));


    	   $data=CHtml::listData($data,'category_id','category_name');

           

    	   foreach($data as $value=>$category_name)

    	   {

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

    	   }   

 

        }     

}

Have you inserted "category_id" in rules() method of model?

In ‘safe’ line,

array(‘tags, category_id’, ‘safe’),




public function rules()

{

    // NOTE: you should only define rules for those attributes that

    // will receive user inputs.

    return array(

        array('title, content, blog_status', 'required'),

        //array('blog_status', 'in', 'range'=>array(1,2,3,4)),

        array('title', 'length', 'max'=>128),

        array('tags', 'match', 'pattern'=>'/^[\w\s,]+$/', 'message'=>'Tags can only contain word characters.'),

        array('tags', 'normalizeTags'),


        array('title, category_id, status', 'safe', 'on'=>'search'),

    );

} 



i add "array(‘tags, category_id, status’, ‘safe’, ‘on’=>‘search’), " in Blog model, but problem persist. the category_id still null.


CDbCommand failed to execute the SQL statement: SQLSTATE[HY000]: 

General error: 1364 Field 'category_id' doesn't have a default value. 

The SQL statement executed was: 

INSERT INTO `skn_blog` (`title`, `content`, `tags`, `blog_status`, `update_time`, `create_time`, `author_id`) 

VALUES (:yp0, :yp1, :yp2, :yp3, :yp4, :yp5, :yp6) 

$model does not has category_id value. i wonder if $model parameter in _form.php is in wrong position?


echo CHtml::dropDownList('category_id',$model, array(),

array('empty' => '-- select topic --'));

because in another example i find $model paramater should be in front after "(" mark, like example below. but, if i change to the example below, the dependent dropdown does not work, after i choose a topic from dependent menu, the category does not change at all.


echo CHtml::dropDownList($model,'category_id', array(),

array('empty' => '-- select topic --'));

thank you for your code suggestion, i already running out idea :wacko: . if you have other clue, please let me know. thanks.

First, in rules() add this line:




array('title, category_id, status', 'safe'),



so these fields will be safe for all scenarios.

Then, this is correct syntax for dropDownList:




echo CHtml::dropDownList($model,'category_id', array('empty' => '-- select topic --'));



Now, write me code of first dropDownList that when it changes reload categories dropdown.

i did, i already post in my response above, after you ask me to write it.


array('title, category_id, status', 'safe', 'on'=>'search'),



the BlogController already posted above. i post here only the function which response to dropdown change in _form.php


public function actionGetCategoryByTopic()

{

   $data=Category::model()->findAll('topic_id=:topic_id',

            array(':topic_id'=>(int) $_POST['topic_id']));


   $data=CHtml::listData($data,'category_id','category_name');


   foreach($data as $value=>$category_name)

   {

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

   }   

}  

and code below is the whole _form.php. i put this mark "//=====" in order to ease you find the dropdown that trigger actionGetCategoryByTopic.

i also edit the "echo CHtml" to this, like you said.




echo CHtml::dropDownList($model,'category_id', array(),

array('empty' => '-- select topic --'));

_form.php




<div class="form">


    <?php 

            $form=$this->beginWidget('bootstrap.widgets.TbActiveForm',array( 

            'id'=>'blog-form',

            'enableAjaxValidation'=>false,

    )); ?>


        <p class="help-block">Fields with <span class="required">*</span> are required.</p>


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


        <?php 

            echo $form->labelEx($model,'title');

            echo $form->textField($model,'title',array('class'=>'span5','maxlength'=>128));

            echo $form->error($model,'title');

        ?>


        <?php 

//==============================================================================        

            $topic=new Topic();


            echo $form->labelEx($topic,'topic_id');

            echo CHtml::dropDownList('topic_id','',Topic::getTopics(''),


                array(

                    'prompt'=>'-- select topic --',

                    'ajax' => 

                        array(

                            'type'=>'POST', 

                            'url'=>CController::createUrl('skn/Blog/GetCategoryByTopic'),

                            'update'=>'#category_id', 

                            'data'=>array('topic_id'=>'js:this.value'),

                        )

                )


            );


            echo $form->error($topic,'topic_id');


            //NEED TO TRY ANOTHER EXAMPLE

            //http://www.yiiframework.com/wiki/429/an-easy-solution-for-dependent-dropdownlist-using-ajax/

            echo $form->labelEx($model,'category');

            echo CHtml::dropDownList($model,'category_id', array(),array('empty' => '-- select topic --'));

            echo $form->error($model,'category_id'); 

//==============================================================================            

        ?>     


        <?php 

            $this->widget('ext.editMe.widgets.ExtEditMe', array(

                'model'=>$model,

                'attribute'=>'content',

            ));        

        ?>        


        <?php 

            echo $form->labelEx($model,'tags'); 

            $this->widget('CAutoComplete', array(

                    'model'=>$model,

                    'attribute'=>'tags',

                    'url'=>array('suggestTags'),

                    'multiple'=>true,

                    'htmlOptions'=>array('size'=>50),

            ));

            echo '<p class="hint">Please separate different tags with commas.</p>';

            echo $form->error($model,'tags');         

        ?>


        <?php 

            echo $form->labelEx($model,'blog_status');

            echo $form->dropDownList($model,'blog_status',PostStatus::getPostStatus('BlogStatus'));

            echo $form->error($model,'blog_status');

        ?>


        <div class="form-actions">

            <?php $this->widget('bootstrap.widgets.TbButton', array(

                    'buttonType'=>'submit',

                    'type'=>'primary',

                    'label'=>$model->isNewRecord ? 'Create' : 'Save',

            )); ?>

        </div>


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

</div>



You are not carefully reading my answer.

I didn’t write what you wrote, but i wrote:




array('title, category_id, status', 'safe'),



Note that i’m missing ‘on’ => ‘search’ attribute.

In this way, you will consider these fields ‘safe’ for all scenarios, also

for create and update scenario.

apologize. the - ‘on’ => ‘search’ - is from the generator. but ok, i already remove it now.

Now you should be able to save the category_id value to db.

like i told you, if i use this :


echo CHtml::dropDownList($model,'category_id', array(),

array('empty' => '-- select topic --'));

the dropdown doesnot work.

but these both work.


echo CHtml::dropDownList('category_id',$model, array(),

array('empty' => '-- select topic --'));


echo CHtml::dropDownList('category_id','', array(),

array('empty' => '-- select topic --'));

but, by using the work code, the category_id return null.

You are making some errors.

First: you are using CHtml with $model.

CHtml::dropDownList signature is:




public static string dropDownList(string $name, string $select, array $data, array $htmlOptions=array ( ));



$model not appear as parameter. $model parameter appear when you use CForm::dropDownList (in your form’s model accessible via $form variable).

So your first line code could be:




echo CHtml::dropDownList('BaseBlog[category_id]', array(),

array('empty' => '-- select topic --'));



Pay attention to the fact that dropDownList first parameter is array of name BaseBlog (if this is your model’s name) and his parameter is field name, “category_id”.