I have a view that shows 2 gridviews of the same model class, however, they seem to use the same filter, sort and pagination, even though they use different search models and dataProviders like so:
In the controller:
public function actionIndex()
{
$searchModel = new CasoAccionSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$dataProvider->pagination->pageParam = "tarea-propia-page";
$dataProvider->sort->sortParam = "tarea-propia-sort";
$searchModelTerceros = new CasoAccionSearch();
$dataProviderTerceros = $searchModelTerceros->search(Yii::$app->request->queryParams);
$dataProviderTerceros->pagination->pageParam = "tarea-3ros-page";
$dataProviderTerceros->sort->sortParam = "tarea-3ros-sort";
return $this->render('myIndex', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'searchModelTerceros' => $searchModelTerceros,
'dataProviderTerceros' => $dataProviderTerceros,
]);
}
And in the view:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
// ['class' => 'yii\grid\SerialColumn'],
'acc_referencia',
'acc_fecha_accion',
'fecha_creacion',
[
'label' => 'Creado Por',
'format' => 'raw',
'value' => function($data){
return $data->abCreador->nombreCompleto;
}
],
//'ab_creacion',
[
'label' => 'Caso',
'format' => 'raw',
'value' => function($data){
return Html::a($data->caso->caso_nombre,
Yii::$app->urlManager->createUrl(['caso/view','id'=>$data->caso_id]));
}
],
// 'caso.caso_nombre',
'acc_descripcion:ntext',
'caso.caso_referencia',
[
'label' => 'Cliente',
'format' => 'raw',
'value' => function($data){
return Html::a($data->caso->cliente->nombreCliente,
Yii::$app->urlManager->createUrl(['cliente/view','id'=>$data->caso->cl_id]));
}
],
// 'resp_id',
// 'acc_tipo',
// 'estado',
// 'acc_horas_estimadas',
// 'acc_horas_ejecutadas',
// 'acc_fecha_accion',
// 'acc_descripcion:ntext',
// 'fecha_creacion',
// 'ab_creacion',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?= GridView::widget([
'dataProvider' => $dataProviderTerceros,
'filterModel' => $searchModelTerceros,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'acc_referencia',
'acc_fecha_accion',
'fecha_creacion',
'caso.caso_nombre',
[
'label' => 'Responsable',
'format' => 'raw',
'value' => function($data){
return $data->abResponsable->nombreCompleto;
}
],
//'abResponsable.ab_nombres',
'acc_descripcion:ntext',
'caso.caso_referencia',
[
'label' => 'Cliente',
'format' => 'raw',
'value' => function($data){
return Html::a($data->caso->cliente->nombreCliente,
Yii::$app->urlManager->createUrl(['cliente/view','id'=>$data->caso->cl_id]));
}
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Any ideas about how to make them behave independently?
I see you have already configured different pagination and sorting parameters for both models. That is correct, so all you need to fix is filtering.
Your filtering applies to both grids, because your form element names are the same. Your search model has the formName() method, which returns a string. By default, it returns class name. So, when you try to filter on acc_referencia in any of the forms, the following parameter is added to your url: CasoAccionSearch[acc_referencia]. It is then picked up by both grids which is not your desired behavior. What you should make instead is grid1[acc_referencia] for first grid and grid2[acc_referencia] for second grid.
You have two choices here: either implement CasoAccionSearch::formName() in such a way that it returns two different form names for two different instances of CasoAccionSearch, or just use two different search models.
I suggest you do it this way:
class CasoAccionSearch
{
public $formNameParam = 'CasoAccionSearch';
// ...
// other attributes
public function formName()
{
return $this->formNameParam;
}
// ...
// other methods
}
And then in your view:
$searchModel = new CasoAccionSearch(['formNameParam' => 'grid1']);
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
For consistency, I would also make pageParam and sortParam attributes of CasoAccionSearch that get passed to the data provider in search().
They use the same class CasoAccionSearch() and then the same search function .. if you need two separated function you need a proper search function eg:
class CasoAccionSearch extends CasoAccion
{
.....
public function search($params)
{
.......
}
public function search2($params) // searc for second grid
{
.......
}
and the adapt you controller/action code for use the two different search function ..
Related
I have install the miloschuman\highcharts\Highcharts, website : https://www.yiiframework.com/extension/yii2-highcharts-widget. I have a database with the table columns lme_price and lme_name which I want to display the price of the copper in the highcharts. I'm using PHP.
Below is my code which I have done. This is the code in my models. I create a static function with the query inside it to find the data that I want from the database.
public static function getCopperPrice()
{
$getCopperPrices = Lme::find()
->select('lme_price')
->where(['lme_name' => 'LME Copper'])
->all();
return $getCopperPrices;
}
Here is my code in the view. I have a table show in the view which show every data from the database.
<div class="lme_index">
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'searchModel'=> $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'label'=> 'DATE',
'attribute' => 'lme_title',
],
[
'label'=> 'MATERIAL',
'attribute'=> 'lme_name',
],
[
'label'=> 'PRICE (US$)',
'attribute'=> 'lme_price',
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Here is the code for the highcharts graph.
<div class = "graph">
<?= Highcharts::widget([
'options' => [
'title' => ['text' => 'Copper Price'],
'xAxis' => [
'categories' => []
],
'yAxis' => [
'title' => ['text' => 'Price $US']
],
'plotOption' => [
'series' => [
['name' => 'Copper',
'data' => [lme::getCopperPrices()]],
]
]
]
]);?>
I want to display only 1 material price in the highcharts. I call the function from the model inside the series but the graph shows nothing on it. The coding there didn't show any error to me.
Can someone help me or tell me how to solve this? Thanks.
Chart require integer values to display
public static function getCopperPrice()
{
$cooperPrices = [];
$copperPriceList = Lme::find()
->select('lme_price')
->where(['lme_name' => 'LME Copper'])
->column();
foreach($copperPriceList as $price) {
$cooperPrices[] = (int) price;
}
return $cooperPrices;
}
I want to use Select2 dr as filter in Yii Grid view, but it doesn't filter at all, only refreshes the page.
I take the data from 2 tables - from accounts I take only user_id, and from credits I take everything else. And every filter works, except And the 'user_id' one.
<?php
echo GridView::widget(
[
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'wp_id',
'value' => 'accounts.user_id',
'filter' => Select2::widget(
[
'model' => $searchModel,
'attribute' => 'wp_id',
'data' => ArrayHelper::map(Accounts::find()->all(), 'wp_id', 'user_id'),
'options' => ['placeholder' => ' --Filter by user id-- '],
'language' => 'en',
'pluginOptions' => [
'allowClear' => true,
],
]
),
],
],
]
); ?>
Here is the action in the controller.
<?php
public function actionIndex()
{
$searchModel = new CreditsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
} ?>
And this is the search model method
<?php
public function search($params)
{
$query = Credits::find()->with('accounts');
$dataProvider = new ActiveDataProvider([
'query' => $query
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
if(!empty($this->user_id)) {
$query->andFilterWhere(['=', 'accounts.user_id', $this->user_id]);
}
// grid filtering conditions
$query->andFilterWhere([
'user_id' => $this->user_id,
'wp_id' => $this->wp_id,
'credits_bought' => $this->credits_bought,
'purchase_date' => $this->purchase_date,
'id' => $this->id,
]);
return $dataProvider;
}
} ?>
Thanks in advance!
Because you are passing the wp_id under the GridView filter and selecting the wp_id from the Accounts model as the value of the select2-dropdown
ArrayHelper::map(Accounts::find()->all(), 'wp_id', 'user_id')
Although it is confusing that you use the gridview column attribute wp_id and use the select2 to filter the user_id for the same column but if you are looking to do that you might need to change the above to
ArrayHelper::map(Accounts::find()->all(), 'user_id', 'wp_id')
I have 3 tables and i have made relation to What table by using Field table. i want to show name row from What table in Gridview.but it shows me row of data seperated by comma. i want each data in different column. like sql query result with repeated field.
this is my tbon.php model:
public function getWhat()
{
return $this->hasMany(What::className(), ['idw' => 'idw'])
->viaTable('Field', ['id' => 'id']);
}
public function getField()
{
return $this->hasMany(Field::className(), ['id' => 'id']);
}
and in TbonSearch.php i have added these codes:
public $what;
public $field;
and
[['field','what'],'safe']
and in search method, i have added:
$query = Tbon::find()
->joinWith(['field'])
->joinWith(['what']);
and for sorting:
$dataProvider->sort->attributes['what'] = [
'asc' => ['what.name' => SORT_ASC],
'desc' => ['what.name' => SORT_DESC],
];
and add search filter:
->andFilterWhere(['like', 'what.name', $this->what]);
in index i have added this code and here is the problem, i think:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'label'=>'Name',
'attribute' => 'what',
'value' => function ($data) {
$str = '';
foreach($data->what as $name) {
$str .= $name->name.',';
}
return $str;
},
],
data is like this: a,b,c,d for field of name! but i want ID and a then in next row ID and b and etc.
any help will be appreciated!
I dont know your code and I dont get the meaning, but I can answer in general.
A GridView is used to view Data in a Grid. A row in a GridView represents a dataset and presenting data in the form of a table.
foreach($data->what as $name) {
$str .= $name->name.',';
}
I assume you want to display the Name attribute from the relation what. You can simply achieve this with the tablename.columnname syntax.
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'label'=>'Name',
'attribute' => 'what.name',
],
If you want to display the ID column additionally:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'label'=>'Name',
'attribute' => 'what',
'value' => function ($data) {
$str = '';
foreach($data->what as $name) {
$str .= ' ';
$str .= $name->id.'';
$str .= $name->name.',';
}
return $str;
},
],
To be more precise (in Terms of your Problem). We have a datamodel with a junction table like the following simple book database.
Example:
If you want to display the names of the authors on the standard CRUD generated index Gridview, you can do something like this:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'book_name',
[
'label'=>'Author(s)',
'value' => function ($dataProvider) {
$str = '';
foreach($dataProvider->authors as $name) {
$str .= ' ';
$str .= $name->id.' ';
$str .= $name->author_name.',';
}
return $str;
},
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
with the result:
In addition, you can edit the Detail View to display such an information in an extra Gridview. The result can look like this.
To achieve this you have to:
add a data provider to your controller and pass the provider to the view
add a gridview widget in your view and connect the data provider
add a method to your model which crawls the data
view.php aka the view
use yii\grid\GridView;
// other code
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
[
'attribute' => 'author.author_name',
'header' => 'Author(s)',
],
],
]); ?>
BookController.php aka the controller
public function actionView($id)
{
$dataProvider = Book::getAllAuthors($id);
return $this->render('view', [
'model' => $this->findModel($id),
'dataProvider' => $dataProvider,
]);
}
Book.php aka the model
use \yii\data\ActiveDataProvider;
// other code
public static function getAllAuthors($id) {
$query = BookAuthor::find()->where(['book_id' => $id]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
return $dataProvider;
}
I have being struggling with related model data for a while and can't seem to pin point the problem, I have been reduced to using a very simple example.
I have two models Dog and Owner, which have the following relations.
Owner:
public function getDogs()
{
return $this->hasMany(Dog::className(), ['owner_id' => 'id']);
}
Dog:
public function getOwner()
{
return $this->hasOne(Owner::className(), ['id' => 'owner_id']);
}
As a simple test I want to get the dog to disaply from the grid view in the index page in Owner view
This is my index.php in the Owner view
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'name',
[
'attribute' => 'type',
'value' => 'dog.type',
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
I must be missing something fundamental here?
You cannot display multiple related items like this, but you could simply use a callback, e.g. :
[
'label' => 'Dog types',
'value' => function($model) {
return join(', ', yii\helpers\ArrayHelper::map($model->dogs, 'id', 'type'));
},
],
I have two database tables 'user' and 'role'. I used Yii framework 2.0 Gii to create CRUD with User model and UserSearch model. By default, Gii uses GridView::widget for the index page for the 'user' model.
In the search($params) method inside of the UserSearch model, I used the following code to join the above tables together
$query = User::find()->with('role');
Everything works fine with the query.
By default Gii does not include the data from the joined table 'role' in the GridView::widget inside of the views/user/index.php page. With the join query above I could retrieve data from both tables. In the views/user/index.php page I have injected the GridView::widget with the following code so that it also includes the data and column names from the joined table (role).
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'userid',
'username',
'role.role_name',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Everything works fine with the role data 'role_name included in the GridView::widget. But the problem is that there is no search box for the role_name. The GridView::widget creates search box for the User properties only. Is there any way to add search box for the properties of the joined table 'role' because I also would like to search through 'role_name' as well as through other properties of the User model.
Try this way:
In your UserSearch model add
UserSearch extends ...
{
public $roleFilterInputName; //the name of the filter search input
//important
function rules()
{
//add roleFilterInputName as safe
return [
[['xxx', 'roleFilterInputName'], 'safe'], //!!!!
];
}
}
in your grid:
'columns':
[
//...
[
'attribute' => 'roleFilterInputName',
'value' => 'role.role_name'
],
//...
]
in UserSearch::search()
$query->andFilterWhere(['like', 'role.role_name', $this->roleFilterInputName])
But I guess you'll have to use 'joinWith' instead of 'with'.
Inside CGridView add below code. It will enable filter with dropDownList.
[
'attribute' => 'act_role_id',
'label' => 'Actor Role',
'value' => 'actRole.role_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\ActorRole::find()->orderBy('role_name')->asArray()->all(),'act_role_id','role_name')
],
CGridView code Snippet is as below:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'userid',
'username',
[
'attribute' => 'act_role_id',
'label' => 'Actor Role',
'value' => 'actRole.role_name',
'filter' => yii\helpers\ArrayHelper::map(app\models\ActorRole::find()->orderBy('role_name')->asArray()->all(),'act_role_id','role_name')
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Try it with
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'userid',
'username',
//'role.role_name',
['attribute' => 'role', 'value' => 'role.role_name'],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
I just have tried it in my code, so I'm not sure if this works also with your code. But if so, I don't know why it has to be defined this way.
I guess the answer of rajesh ujade also includes this definition, however, for Yii 1.
This worked for me
Table = Lead (id , year_id)
Table = Year (id, text)
Added text in lead (index.php)
Year::find()->all() = This code pull all value from table/ all years.
[
'attribute'=> 'year_id',
'format' => 'html',
'value' => 'year.value',
'label' => 'Year',
'filter' => Html::activeDropDownList($searchModel, 'year', yii\helpers\ArrayHelper::map(Year::find()->all(), 'year_id', 'value'), ['class' => 'form-control', 'prompt' => '---']),
],
Also it shows dropdown as well sorting.
image Showing Dropdown in Grdiview
#Ekonoval is going in right way.
Just add following in serch function of UserSearch:
After initializing ActiveDataProvider object like this:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 5,
],
]);
$dataProvider->sort->attributes['roleFilterInputName'] = [
'asc' => ['role.role_name' => SORT_ASC],
'desc' => ['role.role_name' => SORT_DESC]
];
You may write query in your UserSearch model like
if($this->role)
{
$query->join('LEFT JOIN','role','role.user_id = user.id')->andFilterWhere(['role.item_name' => $this->role]);
}