CGridView Relation

Not sure if I’m doing this correctly - I’m trying to create a Product ordering system via a CGridView. The grid is displayed for the Product table.

Table Product:


id

product_name

description

etc…

Table Basket:


product_id

quantity

etc…

Now what I plan to do is have a dropdown on each row in my CGridView which allows me to select the quantity required of a product. Upon selecting a quantity, an ajax request is made that inserts a record in the ‘Basket’ table with the product_id and quantity of the product.

Now for this to work properly, the quantity field in my CGridView will need to fetch the quantity value for any products that have a record in the ‘Basket’ table. This is where I’m struggling at the moment. I created the following relation in my ‘Product’ model:


'basket_items'=>array(self::HAS_ONE, 'Basket', 'product_id'),

And the following is the column in my CGridView:




array(

	'name'=>'basket_items.quantity',

	'value'=>'CHtml::activeDropDownList($data->basket_items, "quantity", $data->Quantities)',

	'type'=>'raw',

),



(In the above code, $data->Quantities is a function which returns an array of key=>value pairs, to create the options for the dropdown.)

The problem with this is now it expects to find a record in the ‘Basket’ table for every product_id that exists in the ‘Product’ table.

What I want it to do is if a record does not exist in the ‘Basket’ table then it should just select a default value from the dropdown. What is the correct way to do this?

Anyone able to advise? Thanks.

I am not sure if I understood your problem, but I am guessing you have to pass a fourth parameter with htmlOptions and an options array inside. The best way is probably to create one more method which would check for your condition and return array(‘options’ => array($default_value => array(‘selected’=>‘selected’))) or an empty array otherwise.

Since you use ajax for saving, why not declare a public attribute in the primary model and pass it ($data, "dummy_quantity") to the activeDropDownList.

I’m don’t know for sure if you can populate “dummy_quantity” conditionally in afterFind() (from $this->basket_items), you have to investigate.

(untested)

/Tommy

This is probably easier than it seems, so I will try and resolve this from the start - can you advise whether the relation I have created is correct for what I am trying to do (and in the correct model)? I have never used HAS_ONE relation type before but it was the only one that (half) works for me in this instance.

Seems right to me. Think of it as a HAS_MANY with limit 1, returning the one and only AR object instead of an array of AR objects. Thus, Product has Basket(s). Basket definitely BELONGS_TO Product.

/Tommy

Cheers tri. Now I have tried to understand your previous comment, where you say "pass it ($data, "dummy_quantity") to the activeDropDownList.

The problem is not about specifying the "dummy_quantity" - but the fact that $data (or $model in my case) is null. This is because if the product_id does not exist in the Basket table then it returns null.

What I meant was to add the dummy attribute to the Products model and initialize it from the related record (if present). But perhaps this would not be a good idea.

As you will need to always display a dropdownlist, perhaps CHtml::dropDownList would be a better choice. Possibly you can insert a trinary operator for the select parameter, something like this




isset($data->basket_items) ? $data->basket_items->quantity : ""



(Not tested now, to me it looks like the select parameter can contain a value to be compared to listData)

/Tommy