Jump to content
Larry Ullman's Book Forums

Dropdown Filter In Cgridview Using Related Model


Philip
 Share

Recommended Posts

Hi guys

 

In the book there is a tutorial showing how to create a filter in cgridview using a related model. This works great for me and I'm able to filter the list fine. However, in my instance, there can only ever be two things to filter '5' ECTS points and '10' ECTS points, so I'd rather have a dropdown menu. I've tried to implement it but I keep getting an error "Trying to get property of non-object" at

$model->course->ects_points

 

Here is the section in CGridView

array(
            'header'    => 'ECTS',
            'name'      => 'course',
            'value'     => '$data->course->ects_points',
            'filter'    => CHtml::dropDownList('Course[ects_points]',
                $model->course->ects_points, array(
                        5 => 5,
                        10 => 10),
                array('empty' => 'All')),
        ),

If I remove the filter, I get a textfield filter which works fine.

Thanks

Link to comment
Share on other sites

If you are getting the 'property of non-object' error you need to take a look at your model relations make sure they are correct. Is the relationship HAS_ONE or HAS_MANY? If this is a non-object it could be an empty array or an array of objects, just have a look into Ralational Active Record (RAR) in more detail.

 

http://www.yiiframework.com/doc/guide/1.1/en/database.arr

 

If you show your models and relations it is easy to work out what is wrong if you need more help?

Link to comment
Share on other sites

Hi Edward

 

My models Course and CoursePeriod have a One-To-Many relationship as defined in their relations:

 

Course

'coursePeriods' => array(self::HAS_MANY, 'CoursePeriod', array('course' => 'course_id')), 

CoursePeriod

'course' => array(self::BELONGS_TO, 'Course', array('course' => 'course_id')), 

So basically one course can have many course periods.

 

I think that the relations are ok, as it works fine when I don't explicitly set the filter, as I get a textfield which which filters when I enter 5 or 10. I get no records as expected if I put something else in.

 

 

If you are getting the 'property of non-object' error you need to take a look at your model relations make sure they are correct. Is the relationship HAS_ONE or HAS_MANY? If this is a non-object it could be an empty array or an array of objects, just have a look into Ralational Active Record (RAR) in more detail.

 

http://www.yiiframework.com/doc/guide/1.1/en/database.arr

 

If you show your models and relations it is easy to work out what is wrong if you need more help?

Link to comment
Share on other sites

I just checked over your model relations i can confirm they are correct. I will try implementing this type of drop down filter into one of my CGridView's and see if i can get it working now.

 

Update: I managed to get the dropdownlist working and now i have it working the same as you did with that same error coming up "Trying to get property of non-object". Okay i will figure this out!

Link to comment
Share on other sites

Thanks Edward,

 

I think I am doing something wrong in my search() criteria and the name of the filter in gridview too.

as a little back ground, my gridview is pulling from CoursePeriod, which has a foreign key in Course as basically courses are being reused every year. So CoursePeriod contains a course id call "course" which points to "course_id" in Course.

I'd like to be able to add more information to the gridview such as course_name, ects_points and course level, all of which are contained in Course. I can get all the data to display using 

'value'=>'$data->course->course_name'

 etc, but if I want to filter on each of these columns, I need to relate them back to Course somehow.

 

At the moment I have the ects_points dropdown set up with 'name'=>'course', but this can't be correct, as what would I use for the others that are also related to Course? I would have thought 'name' should be something like 'course.ects_points' but this doesn't work.

In my CoursePeriod search method I have the following:

$criteria=new CDbCriteria;
$criteria->with = 'course';
$criteria->compare('id',$this->id);
$criteria->compare('course.ects_points',$this->course);
... // and so on 

I should note that when I say that the filtering works with ects_points without the 'filter' element, it works, but all the columns change slightly (become smaller) so there seems to be an error somewhere.

Link to comment
Share on other sites

Well if you think about this more carefully you can't display the 5 or 10 in your current CGridView results as this is HAS_MANY data and not BELONGS_TO in which you could bring up the relational data for.

 

So the point being you can only display the data in a particular column for data that BELONGS_TO if you wish to get data for HAS_MANY you will need to loop through the array of objects with a foreach loop that is after checking that the returned array is not empty (which you can use the array function count() to test this).

 

Therefore the "Trying to get property of non-object" is not coming from the dropdownmenu but the code below.

'value'     => '$data->course->ects_points',

You are saying that a course could have a 5 and a 10 or am i confused with something here.

Link to comment
Share on other sites

The thing is that I am actually able to display ects points and I can also filter them using at text field, it's just the dropdown that isn't working. 

so this works:

array(
            'header'    => 'ECTS',
            'name'      => 'course',
            'value'     => '$data->course->ects_points',

but this doesn't

array(
       'header'    => 'ECTS',
       'name'      => 'course',
       'value'     => '$data->course->ects_points',
       'filter'    => CHtml::dropDownList('Course[ects_points]',
           $m->course->ects_points, array(
                  5 => 5,
                  10 => 10),
           array('empty' => 'All')),

A course can have either 5 or 10 ects points which is why I want to filter courses using a dropdown.

Hmmm I guess I'll have to give it a thorough look through to see if I am misunderstanding something with the relationships. I'm fairly new to Yii. :-)

Link to comment
Share on other sites

I'm sorry i am confused with what is going on here, it only works in my model if the relationship is BELONGS_TO. Its hard to look at your tables because even with the relationships you have given i don't understand fully what the data is you need to manipulate. The structure of the tables and the data they contain is also important to getting things correct. Well good luck this!

Link to comment
Share on other sites

Sorry, it can also be difficult to know how much to post without overwhelming the thread and I do appreciate your help!

anyway as I've mentioned, I have two tables:

CoursePeriod: id, course, term, year, start_date, end_date, other_non_important_logging_fields

Course: course_id, course_name, department, course_level, ects_points

 

CoursePeriod.course is a foreign key to Course.course_id

 

My gridview is pulling from CoursePeriod and displays the following columns:

 

Course.course_name, Course.course_level, CoursePeriod.CourseDates, Course.ects_points

 

CourseDates comes from getCourseDates() in CoursePeriod, but I'm not concerned about filtering this. The only columns that have to be filter are the related columns with course_name as a textfield,  course_level and ects_points as dropdowns.

 

I hope that this makes more sense to you now.

Thanks again for your help

Link to comment
Share on other sites

Hi Edward,

 

I think I have solved half the problem anyway. I found an article here which helped.

I've gotten filtering to work on the related columns by adding properties to the CoursePeriod model.

For example, to get textfield filtering working on Course.course_name and Course.ects_points I added the following properties in the CoursePeriod model:

public $search_ects_points;
public $search_course_name;

I then added them to the rules

... search_ects_points, search_course_name', 'safe', 'on'=>'search'),

in the search method I added the following

$criteria->compare('course.ects_points',$this->search_ects_points, true);
$criteria->compare('course.course_name',$this->search_course_name, true);

which means I can now do this in the view

array(
       'header'    => 'ECTS',
       'name'      => 'search_ects_points',
       'value'     => '$data->course->ects_points',

and it seems to work fine on both columns.

What I am missing now is the dropdown on ects_points.

I tried this: 

'filter' => CHtml::dropDownList('Course[ects_points]',
             $model->search_ects_points, array(
                '5' => '5',
                '10' => '10'),
              array('empty' => 'All')),

but it doesn't filter. I don't get an error and there is a dropdown filter with all, 5 and 10, but on selecting 5 or 10, the grid just refreshes. I'm sure I'm close and I'm kinda shooting in the dark, but I'll get there. If you have any ideas regarding this, feel free to post. I'll post my fix if I come up with it.

Link to comment
Share on other sites

I got it working by using listdata in the end.

'filter' => CHtml::listData(CourseEcts::model()->findAll(), 'id', 'ects_points'),

I had to create a model for CourseEcts points and now I get a dropdown with the ects points which filters perfectly. It's not the most elegant of solutions as the dropdown is not based on the data in the gridview, but thats a separate issue that I'll come back to later. 

Thanks for all your help and suggestions! :-)

  • Upvote 2
Link to comment
Share on other sites

 Share

×
×
  • Create New...