[SOVLED] CHtml::activeCheckBoxList - how to pass data

I've following DB structure:

table news:



CREATE TABLE  `scrawroc`.`news` (


  `id` mediumint(8) unsigned NOT NULL auto_increment COMMENT 'id',


  `title` varchar(100) collate utf8_polish_ci NOT NULL COMMENT 'title of news',


  `author_desc` varchar(20) collate utf8_polish_ci NOT NULL COMMENT 'author of news',


  `date` date NOT NULL COMMENT 'date when posted',


  `time` time NOT NULL COMMENT 'time when posted',


  `author_id` smallint(5) unsigned default NULL,


  `total_comments` mediumint(8) unsigned NOT NULL default '0',


  `published` tinyint(1) NOT NULL default '0',


  PRIMARY KEY  (`id`),


  KEY `FK_news_1` (`author_id`),


  CONSTRAINT `FK_news_1` FOREIGN KEY (`author_id`) REFERENCES `user` (`id`) ON DELETE CASCADE


) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci COMMENT='news';


table category:



CREATE TABLE  `scrawroc`.`category` (


  `id` tinyint(3) unsigned NOT NULL auto_increment,


  `category` varchar(40) collate utf8_polish_ci NOT NULL,


  `description` varchar(100) collate utf8_polish_ci NOT NULL,


  PRIMARY KEY  (`id`)


) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci COMMENT='news categories';


table news_category



CREATE TABLE  `scrawroc`.`news_category` (


  `id` mediumint(8) unsigned NOT NULL auto_increment COMMENT 'id',


  `news_id` mediumint(8) unsigned NOT NULL COMMENT 'ID of news',


  `category_id` tinyint(3) unsigned NOT NULL COMMENT 'ID of category',


  PRIMARY KEY  (`id`),


  KEY `FK_news_id` (`news_id`),


  KEY `FK_categoryid` (`category_id`),


  CONSTRAINT `FK_categoryid` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE,


  CONSTRAINT `FK_news_id` FOREIGN KEY (`news_id`) REFERENCES `news` (`id`) ON DELETE CASCADE


) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci COMMENT='describes categories where belong news';


…and following model classes:

News



class News extends CActiveRecord{


/../


public function relations()


{


  return array(


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


    'comments'=>array(self::HAS_MANY, 'NewsComment', 'news_id', 'with'=>'author'),


    'category'=>array(self::HAS_MANY, 'NewsCategory', 'news_id'),


    'txt'=>array(self::HAS_ONE, 'NewsTxt', 'news_id'),


  );


}


/../


}


Category



class Category extends CActiveRecord{


/../


  public function relations()


  {


    return array(


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


      'news'=>array(self::HAS_MANY,'NewsCategory','category_id'),


    );


  }	


/../


}


NewsCategory



class News extends CActiveRecord{


/../


  public function relations()


  {


    return array(


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


    );


  }	


/../


}


How to pass news data for update action to CHtml::activeCheckBoxList() helper to achieve  list of news categories with correct labels (field description from table category) and correct values in checkboxes from news_category table?

You can define a property in your NewsCategory (or Category) AR, and then use CHtml::listData to generate the needed data.

Could you elaborate a little bit about how listData is working? I see there models array, what leads me to conclusion that I can pass there more than one model. How can I distinguish between them?

I guess what you need is a list of value-label pairs to populate the activeCheckBoxList. Using listData() can help you generate this list. You pass in an array of model objects, specify the value property name and the label property name.

I'll try to experiment with this method. Will ask fore more details if I'll stuck

@Qiang: Hi I've abandoned this problem for a few days. Now when I've turn back into it I still can't find the right solution. Forget about this what I've written before. I'llgive you below an example, where I've stuck with CHtml::activeCheckBoxList.

I've following model:



  class NewsModel extends CFormModel 


  {


    


    public $title;


    public $authorId;


    public $authorDesc;


    public $text;


    public $published;


    public $selectedCategories;


    public $allowedCategories;


    


    public function rules()


    {


      return array(


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


        array('authorDesc','length','max'=>20),


        array('title, authorDesc, text, published, categories', 'required'),


        array('authorId', 'numerical', 'integerOnly'=>true),


      );


    }


}


In variable "allowedCategories" I've list of all categories where news may belong to.

In varaible "selectedCategories"  I've list of categories where my News belong to.

Let's imagine that in "allowedCategories" I've following values (array of 3 Category AR with IDs=1,2,3)



array


(


    [0] => Category#1


    (


        [isNewRecord] => false


        [CActiveRecord:_md] => CActiveRecordMetaData#2


        (


            [tableSchema] => CMysqlTableSchema(...)


            [columns] => array(...)


            [relations] => array(...)


            [attributeDefaults] => array(...)


            [CActiveRecordMetaData:_model] => Category(...)


            [CActiveRecordMetaData:_validators] => null


        )


        [CActiveRecord:_attributes] => array


        (


            [id] => '1'


            [category] => 'najnowsze'


            [description] => 'najnowsze newsy'


        )


        [CActiveRecord:_related] => array()


        [CModel:_errors] => array()


        [CComponent:_e] => null


    )


    [1] => Category#3


    (


        [isNewRecord] => false


        [CActiveRecord:_md] => CActiveRecordMetaData#2(...)


        [CActiveRecord:_attributes] => array


        (


            [id] => '2'


            [category] => 'turnieje wrocławskie'


            [description] => 'wyniki turniejów we wrocławiu'


        )


        [CActiveRecord:_related] => array()


        [CModel:_errors] => array()


        [CComponent:_e] => null


    )


    [2] => Category#4


    (


        [isNewRecord] => false


        [CActiveRecord:_md] => CActiveRecordMetaData#2(...)


        [CActiveRecord:_attributes] => array


        (


            [id] => '3'


            [category] => 'turnieje ogólnopolskie'


            [description] => 'wyniki turniejów ogólnoposkich'


        )


        [CActiveRecord:_related] => array()


        [CModel:_errors] => array()


        [CComponent:_e] => null


    )


}


and in "selectedCategories" ( array of 2 NewsCategory AR with IDs=43,44, which assign news 42 with categories ID 1 and 2)



[0] => NewsCategory#1


    (


        [isNewRecord] => false


        [CActiveRecord:_md] => CActiveRecordMetaData#2


        (


            [tableSchema] => CMysqlTableSchema(...)


            [columns] => array(...)


            [relations] => array(...)


            [attributeDefaults] => array(...)


            [CActiveRecordMetaData:_model] => NewsCategory(...)


            [CActiveRecordMetaData:_validators] => null


        )


        [CActiveRecord:_attributes] => array


        (


            [id] => '43'


            [news_id] => '42'


            [category_id] => '1'


        )


        [CActiveRecord:_related] => array()


        [CModel:_errors] => array()


        [CComponent:_e] => null


    )


    [1] => NewsCategory#3


    (


        [isNewRecord] => false


        [CActiveRecord:_md] => CActiveRecordMetaData#2(...)


        [CActiveRecord:_attributes] => array


        (


            [id] => '44'


            [news_id] => '42'


            [category_id] => '2'


        )


        [CActiveRecord:_related] => array()


        [CModel:_errors] => array()


        [CComponent:_e] => null


    )


}


Now this data I'm using for update action for news. I want to display in update action list of all "AllowedCategories" where checked are only "selectedCategories".

I've tried following code:



  <?php echo CHtml::activeCheckBoxList(


    $news,


    'selectedCategories',


    CHtml::listData($news->allowedCategories,'id','category'),


    array('checked'=>CHtml::listData($news->selectedCategories,'id','category'))


  ); ?>


…but without success

The problem is in your selection. First, you do not the 'checked' option because you already specified the selection using the first and second parameters. Second, the selection (i.e., $news->selectedCategories) should give an array of selected values, not objects.

I've changed my code into following:



  <?php echo CHtml::activeCheckBoxList(


    $news,


    'selectedCategories',


    $news->allowedCategories


  ); ?>


where $news is intance of NewsModel and allowedCategories and selectedCategories has following values



//news->allowedCategories


array


(


    [1] => 'najnowsze'


    [2] => 'turnieje wrocławskie'


    [3] => 'turnieje ogólnopolskie'


    [4] => 'ogłoszenie'


    [5] => 'zaproszenie'


    [6] => 'sukcesy klubowe'


    [7] => 'sukcesy indywidualne'


    [8] => 'rekordy klubowe'


    [9] => 'zdjęcia'


    [10] => 'ciekawostki'


    [11] => 'pfs'


    [12] => 'wydarzenia'


    [13] => 'turnieje'


    [14] => 'paśnik'


) array


//news->selectedCategories


(


    [1] => 'checked'


    [2] => 'checked'


    [3] => 'checked'


    [4] => 'checked'


    [6] => 'checked'


    [7] => 'checked'


    [8] => 'checked'


    [10] => 'checked'


    [11] => 'checked'


    [13] => 'checked'


Categories are displayed as well, but all checkboxes are unselected

update

I've found reason why it was not working. I've misunderstood idea of secondparameter in activeCheckBoxList. It should contains following values



array


(


    [0] => '1'


    [1] => '2'


    [2] => '3'


    [3] => '4'


    [4] => '6'


    [5] => '7'


    [6] => '8'


    [7] => '10'


    [8] => '11'


    [9] => '13'