Is there a way to show in a Grid that takes it data from CActiveDataProvider some new rows that are not actually yet into the database?
here's my scenario..
I have to fill by X times (the quantity of a product in a bill) and provide to each row the possibility to be edited and saved
Product QTY
product1 3
|
____ Edit item 1 (not yet in the db)
____ Edit item 2 (not yet in the db)
____ Edit item 3 (not yet in the db)
So it's kind of like a master detail grid (That I've sorted it out how to do it..)
but I can't display things on a grid that arren't yet in the database..
I know I have to create an array of temporary models like $model[]=new MODEL(); and push the somehow to the CActiveDataProvider but don't know the syntaxis...
You can't do this with CActiveDataProvider because as the documentation says
CActiveDataProvider provides data in terms of ActiveRecord objects which are of class modelClass. It uses the AR CActiveRecord::findAll method to retrieve the data from database.
However, there is CArrayDataProvider. You can put arbitrary data in it, ie. merge an array of real objects with an array of empty ones and use that.
$rawData=array(
array('id'=>1, 'username'=>'from', 'email'=>'array'),
array('id'=>2, 'username'=>'test 2', 'email'=>'hello#example.com'),
);
$arrayDataProvider=new CArrayDataProvider($rawData, array(
'id'=>'id',
'sort'=>array(
'attributes'=>array(
'username', 'email',
),
),
'pagination'=>array(
'pageSize'=>10,
),
));
As you can see, the data here is a simple array, but you can even sort the data.
Related
I have a model InboxMessageHelper with relations like
'message', 'sender' and 'receiver' and I am using the following criteria to query data:
$model = new CActiveDataProvider('IndividualMessageHelper', array(
'criteria'=>array(
'condition'=>'receiver_id = '.Yii::app()->user->id,
'order'=>'message.created_at DESC',
'with'=>array('message', 'sender', 'receiver'),
'together'=>true,
),
));
I want to get all data (i.e. including the relations data) inside the controller and form a JSON, but the problem is that i cannot access related fields data. I can see that the data is available when I use
CVarDumper::dump()
when I try to encode $model->data then only data from current table gets encoded. How should I go about it?
I don't think CActiveDataProvider can be used in this way. You need to be working with the model. So you'll need something like this in your controller.
$models = IndividualMessageHelper::model()->findAll('receiver_id = '.Yii::app()->user->id);
foreach($models as $model){
$json[] = $model->getAttributes; //This won't get any model properties you've declared
yourself, only database columns
}
//Now get the related records and add them to the array.
array_push($json, $model->getRelated('message')->getAttributes());
array_push($json, $model->getRelated('sender')->getAttributes());
array_push($json, $model->getRelated('receiver')->getAttributes());
echo json_encode($json);
I am using "MvcContrib.Mvc4" to show my grid on a page in my project.
I need to have a grid with some columns which are from filtered data (From Source table), and have 3 in-line editable column, like StartDate, EndDate, Notes and need to insert them into new table(The Destination Table)
I can use the Html.EditorFor(c=>c.StartDate) in my columns, and edit them on the grid, but I don't know how to track the changes and save their updates into data base!
Also I have the column of "Notes" which is not in the model, but I need to insert it into new table with the other changed data (To the destination table)
After I edited data, in the source of page, the value is not changed.
I need to give the user the ability of editing (these three columns) on many rows and after submitting the "Save" button, Save bulk changes from grid into another new table!
I am thinking of a way to get changes and send them all to server by client side code like Jquery or Ajax, But I could not find any good example of this on internet.
I know how to check boxes on the grid and get the selected ids form the page, but I don't know how to get changed Text fields and Dates from grid.
I appreciate any help or sample code!
Here are some codes
#Html.Grid(Model.Enrolments).WithModel(new EnrolmentGrid()).Columns(column =>
{
column.For(i => Html.EditorFor(x => i.EndDate)).Named("End Date");
column.For(i => Html.EditorFor(x => i.StartDate)).Named("Start Date");
column.For(i => Html.Editor("Notes", new { /*Not sure if this is correct*/ value = i.EnrolmentId, #class = "Notes" })).Named("Notes");
}).Attributes(#class => "full-grid-style")}
I have two data sources
1) Database
2) Memcached or Totally different database
From 1st database I am getting the group members list IDs ( has more than 10 thousand rows) and after getting the list I query second database or hit Memcached to get the actual details
$connection = Yii::app()->db;
$sql = 'select user_id,joined_date from group_data where group_id=:group_id ';
$dataProvider = new CSqlDataProvider($sql, array(
'keyField' => 'user_id',
'sort' => array(
'attributes' => array(
'user_id',
'joined_date'
),
'defaultOrder'=>array(
'user_id ASC',
)
),
'pagination' => array(
'pageSize' => 30,
),
'totalItemCount' => $count,
));
$connection_master = Yii::app()->masterdb;
In the above data provider , I am not sure how to include my second database and get the actual user name since it is in other database .No direct connection from one database to other.
Here the problem is pagination is based on the first database table ( 30 records per page) and the actual data is from second table .
Any idea on how to implement this ?
Thank You
You could build your own custom data provider class. You can extend it from CDataProvider and implement the missing abstract methods:
abstract protected function fetchData();
abstract protected function fetchKeys();
abstract protected function calculateTotalItemCount();
Notice, that your storage model already comes very close to these methods: You store the IDs in one database and the actual data in another. So you can focus on one DB at a time in each of these methods.
You'd start with fetchKeys(). There you need to query the keys (=IDs) from your second database. Have a look at CSqlDataProvider::fetchData() to see how to use the CPagination object from $this->getPagination() to find out the current limit and offset. If you need sorting you'd also inspect the CSort object from $this->getSort() for current sort settings. With all that data available you should be able to build the query for the IDs on the currently requested result page.
Then in fetchData() you can obtain those keys through $this->getKeys(). You should not call fetchKeys() directly, because with getKeys() the result from fetchKeys() is "cached", so if it's called again later in the same request, there won't be another query. With that keys you now can easily query your main database. The result will represent the rows on the current page.
Finally you have to implement calculateTotalItemCount(). This is very easy again: Just query your second DB for the total number of items.
That's all you need to do - the code in the base CDataProvider class will take care of the rest and call your methods on demand.
I have a model which has the following relationship declared:
'messages' => array(self::HAS_MANY, 'WallMessages', 'liga_id',
'condition'=>'specific_post.parent_message_id IS NULL',
'order'=>'specific_post.date DESC',
'alias'=>'specific_post'),
Im trying to use this collection within a CListView with a custom pagination. However, if for example my pages are of size 5, i need to get from elements 5 through 10 to populate the view.. How can i get n elements from a defined relationship?
you can use model's serach() or custom CDbCriteria yourself.
CDbCriteria
I'm playing around with the CGridView widget and I'm trying to find out if it would be appropriate to use it in the following context:
Lets say I have two database tables, Car and Accident. Each car may be associated to zero or more accidents. I would like to have a column in the grid view containing the number of accidents for each car, assuming that a row in the grid view represents a car.
Is this feasible using a GridView widget, or should I try some other approach?
You can define relation for your Car model as follows:
public function relations()
{
return array(
'accidents' => array(self::HAS_MANY, 'Accidents', 'Id'),
'accidentsCount' => array(self::STAT, 'Accidents', 'AccidentId'),
);
}
If you use count($model->accidents) then you will load all related models and then use PHP count function to get number of models, if you care about performance and memory you will use stat relation accidentCount to get number of accidents.
If you have the relation "cars have one to many accidents" a simple count on the relation can be used. $model is car here.
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'car-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'name',
array(
'header'=>'Accidents',
'value'=>'count($data->accidents)',
),
),
));
The easiest way is to give the car model a "getNumberOfAccidents()" getter. You can then use that in the grid as a regular column (numberOfAccidents). Easy as pie :)