I want to display the name instead of ID in the DetailView.
I have done similar on what I did in the GridView which is:
[
'attribute' => 'employee_id',
'value' => 'employee.employee_name'
],
But if I try it on DetailView it displays "employee.employee_name" not the Employee Name
Here's my model:
public function getEmployee()
{
return $this->hasOne(Employee::className(), ['id' => 'employee_id']);
}
I've already found the answer I have just read the Yii2 documentation.
The solution is
[
'attribute' => 'employee_id',
'value' => $model->employee->employee_name,
],
I hope this also help the others.
There is even more simpler one line solution
[
'attribute' => 'employee.employee_name'
],
In GridView, you can show the name using the "employee.employee_name" approach.
But "DetailView" Approach is different. You must use the $model approach, which is shown below.
$model->your_relation_name(without prefixing "action")->field_name
//e.g.
[
'attribute'=> 'Employee Name',
'value'=>$model->employee->employee_name;
]
Related
I have 2 models: Order and Product, each has belongsToMany with pivot set properly.
In OrderCrudController, I also use FetchOperation and make a fethProducts() function as below:
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
public function fetchProducts()
{
return $this->fetch([
'model' => \App\Models\Product::class,
'searchable_attributes' => ['name','sku']
]);
// return $this->fetch(\App\Models\Product::class); <-- I also tried this one
}
protected function setupCreateOperation()
{
CRUD::setValidation(OrderRequest::class);
// other fields
$this->crud->addField([
'name' => 'products',
'type' => 'relationship',
'pivotSelect' => [
'attribute' => 'name',
'ajax' => true,
],
'subfields' => [
[
'name' => 'quantity',
'type' => 'number',
],
],
]);
}
But it comes to unexpected behavior when I search the product, the select2 field remains "searching" though the request successfully retrieved the data.
screenshot - select2 field
screenshot - ajax results
PS: this field works perfectly without subfields, no vendor overrides etc., so I think I've set everything correctly.
Anyone can help?
This was asked two months ago but somehow I missed it, just noticed it today after someone opened an issue on the GitHub repository.
I am happy you guys found a solution for it but unfortunatelly I cannot recommend it as using the select2_from_ajax will miss the functionality to don't allow the selection of the same pivots twice, otherwise you will have undesired consequences when saving the entry.
I've just submitted a PR to fix this issue, I will ping you guys here when it's merged, probably by next Monday.
Cheers
I just came accross this exact problem and after quite some research and trials, i finally found a solution !
The problem seems to be related to the relationship field type inside the pivotSelect. Try to use select2_from_ajax instead and don't forget to set method to POST explicitly, that worked for me like a charm.
Here is what you might try in your case :
$this->crud->addField([
'name' => 'products',
'type' => 'relationship',
'pivotSelect' => [
'attribute' => 'name',
'type' => 'select2_from_ajax',
'method' => 'POST',
'data_source' => backpack_url('order/fetch/products') // Assuming this is the URL of the fetch operation
],
'subfields' => [
[
'name' => 'quantity',
'type' => 'number',
],
],
]);
I have this working in GridView:
[
'attribute' => 'attribute',
'value' => function ($model) {
return \Yii::$app->formatter->{$model->format}($model->attribute);
},
],
I want to implement basically the same but into DetailView:
[
'attribute' => 'attribute',
'value' => \Yii::$app->formatter->{$model->format}($model->attribute),
],
$model->format is coming from DB and is e.g. asDecimal.
In DetailView I'm getting the following error:
PHP Fatal Error – yii\base\ErrorException
Method name must be a string
How can I avoid this problem? Can you please point me to the right direction? Thank you!
UPDATE: it's also not working in index pages. It's working only in views, generated with giiant, in gridviews of related data. I see these are somehow strange echoed gridviews, but what is the key difference between a normal gridview, and the one like that:
<?=
'<div class="table-responsive">'
. \yii\grid\GridView::widget([
'layout' => '{summary}{pager}<br/>{items}{pager}',
'dataProvider' => new \yii\data\ActiveDataProvider([
Since Yii 2.0.11 you can use closures in DetailView in the same way as in GridView:
[
'attribute' => 'attribute',
'value' => function ($model) {
return \Yii::$app->formatter->{$model->format}($model->attribute);
},
],
https://www.yiiframework.com/doc/guide/2.0/en/output-data-widgets#detail-view
I have an issue with a Gridview using kartik\grid\EditableColumn, after changing the value I am returned the wrong value for the column when it updates. I am returned the dropdown key/main table integer rather than the string contained in a linked table.
I have two tables
Leads - columns id and status_id
Related fields - model, field, related_value, related_value
The relation is based on in this case
model:"Leads",
field:"status_id",
related_id:status_id
I have the following relation in my model
public function getStatus()
{
return $this->hasOne(RelatedFields::className(), ["related_id" => "status_id"])->andOnCondition(["status.field" => "status_id", "status.model"=>"Leads"])->from(["status" => RelatedFields::tableName()]);
}
I also created the following as a test based on this link
public function getStatusValue()
{
return $this->status->related_value;
}
Here is the column code
[
'class' => 'kartik\grid\EditableColumn',
'attribute' => 'status_id',
'value'=>'status.related_value',
//'value' => function($model){ return $model->status->related_value; },
//'value' => function($model){ return $model->StatusValue; },
//'refreshGrid' => true,//Works but not nice
'vAlign'=>'middle',
'hAlign'=>'center',
'pageSummary' => true,
'readonly' => false,
'width'=>'10%',
'filter'=>Html::activeDropDownList($searchModel, 'status', ArrayHelper::map(RelatedFields::Find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'),['class' => 'form-control','prompt' => Yii::t('app', '')]),
'editableOptions'=> [
//'attribute'=>'status_id',
//'value'=>'status.related_value',
//'header' => 'profile',
//'format' => Editable::FORMAT_BUTTON,
'inputType' => Editable::INPUT_DROPDOWN_LIST,
'data'=> ArrayHelper::map(RelatedFields::Find()->where(['model' =>"Leads","field"=>"status_id"])->all(), 'related_id', 'related_value'),
]
],
Commented out are a number of lines in my attempts to fix the issue as well as combinations of them, however all result in the wrong value.
If for example I select the related value "New" which has a related_id 1, after the column has been updated I get the value 1 instead of "New".
When the table is first loaded/reloaded the value does show correctly.
I could reload the grid, but this seems wrong just to fix 1% of the data shown on the page.
I your model take a public variable $status_value
create an assigning value method
public function getStatusValue()(){
return $this->status_value= $this->status->related_value;
}
Now in Gridview use getStatusValueenter code heremethod with assigning value as below
use yii\helpers\Url;
$gridColumns = [
[
'class' => 'kartik\grid\EditableColumn',
'attribute' => 'status_value',
'pageSummary' => true,
'readonly' => false,
'value' => function($model){ return $model->statusValue; }, // assign value from getStatusValue method
'editableOptions' => [
'header' => 'status_value',
'inputType' => kartik\editable\Editable::INPUT_TEXT,
'options' => [
'pluginOptions' => [
]
]
],
],
];
If you follow Kartik guide, he suggest to add EditableColumnAction to better handle the editable column:
The EditableColumnAction offers a quick easy way to setup your
controller action for updating, saving and managing the EditableColumn
output from GridView. This action class extends from yii\rest\Action
and hence all properties available with yii\rest\Action are applicable
here. The basic setup of the column involves setting up the controller
action and the EditableColumn.
So you need to add an EditableColumnAction in your controller to handle the update of the model:
public function actions()
{
return ArrayHelper::merge(parent::actions(), [
'edit-lead' => [
'class' => EditableColumnAction::class,
'modelClass' => Leads::class
]
]);
}
In your GridView editable column configuration, include the above
controller action for processing the Editable within editableOptions.
For example
And in your column code you need to add the action to editableOptions property:
'editableOptions' => [
...
'formOptions' => ['action' => ['/leads/edit-lead']]
]
Now, according to the guide, you can add to your action the outputValue property:
'outputValue' => function (Leads $model) {
return $model->status->related_value;
}
I have a table like this with 5 columns.
TableName
-Column1
-Column2
-Column3
-Column4
-Column5
I had merged them to display them in grid view as single column.
Question
How can i make filter condition query to search them based on user input.?
Eg.User types something as input, it have search from all the 5 columns and return the result based on the search input.(Sorting works fine, please help me with filtering)
If someone could helpme it would be great,
Thanks.
UPDATE:
$query->andFilterWhere(['ilike', '"x"."y"', $this->variantName]) ->andFilterWhere(['"a"."b"' => $this->ClassId])
->andFilterWhere(['"c"."d"' => $this->FamilyId])
->andFilterWhere(['"e"."f"' => $this->PlatformId])
->andFilterWhere(['ilike', '"g"."h"', $this->subFamilyName])
This is how my old model looks like the fields with familyId,classId,PlatformId are integer and subfamilyname,variantname are text.
Modified:
$query->andFilterWhere(['or',
['ilike', '"x"."y"', $this->Combo],
['"a"."b"' => $this->Combo],
['"c"."d"' => $this->Combo],
['"e"."f"' => $this->Combo],
['ilike', '"g"."h"', $this->Combo],
])
UPDATE 2:
This is how the query looked before merging columns.
->andFilterWhere(['ilike', '"storeNames"."variantName"', $this->variantName])
->andFilterWhere(['"storeNames"."classId"' => $this->malwareClassId])
->andFilterWhere(['"storeNames"."familyId"' => $this->malwareFamilyId])
->andFilterWhere(['"storeNames"."platformId"' => $this->malwarePlatformId])
->andFilterWhere(['ilike', '"storeNames"."subFamilyName"', $this->subFamilyName]);
I will add an example that uses a countries table to display data with GridView.
In order to accomplish what you need you have to take the following steps.
Create a custom attribute/field inside your SearchModel.
Add the field to gridview column.
Define the field as safe inside the rules.
update the search() function inside the SearchModel to search and compare based on the new custom field.
Let's say I have a Countries table with 2 models
Countries
CountriesSearch
The countries table has name and code field and i want to show country name and code inside a single column like below.
and i want that the filter field above on the gridview should be able to search if i type name or code any one of them.
Add field name $combo in the CountrieSearch
public $combo
add the field to the rules as safe
public function rules() {
return [
[ [ 'id' ] , 'integer' ] ,
[ [ 'name' , 'code' , 'combo' ] , 'safe' ] ,
];
}
Add the new field to the gridview
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute'=>'combo',
'label'=>'Name/Code',
'value'=>function($model){
return '<span class="label label-success">'.$model->name.'</span><span class="label label-info">('.$model->code.')</span>';
},
'format'=>'raw',
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Then update the search function and add the following lines just before you are returning the $dataProvider inside the search() method
$query->andFilterWhere ( [ 'OR' ,
[ 'like' , 'name' , $this->combo ],
[ 'like' , 'code' , $this->combo ],
] );
Hope this helps you out
i was looking for a previous answer, but the ones i've found are related to older cakephp versions
i have two tables, 'magazines' and 'issues' where there is a relation 'issues' BelongsTo 'magazines', this is what IssuesTable looks like:
public function initialize(array $config){
$this->belongsTo('Magazines', [
'foreignKey' => 'id'
]);
}
table magazines has two fields, magazines.id and magazines.name
table issues has two fields, issues.id, issues.magazine_id where issues.magazine_id is the foreign key
to populate a select input in the issues view with the magazine.name values and save the issues.magazine_id, i've set the controller like this
$this->set('magazines', $this->Issue->Magazine->find('list'));
then i've added the following code to the issue view add.cpt
<?php
echo $this->Form->input('name', [
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true]);
?>
but i get the input select with the issues.magazine_id as values instead of magazines.name
thanks for your help and comments
You want to use find('list') as this will return the primary key and display field:-
$this->set(
'magazines',
$this->Issues->Magazines->find('list')
);
Then in your form you need the input name to be magazine_id if you're wanting to set the foreign key for the association:-
echo $this->Form->input(
'magazine_id',
[
'type' => 'select',
'multiple' => false,
'options' => $magazines,
'empty' => true
]
);
See the docs for more info.
Update
If you're experiencing issues with find('list') it is perhaps because your model's displayField is not getting set correctly. Cake normally determines the displayField for the model on initialisation. If this isn't working, or you want a different field you can set this manually in the model's initialize() method. E.g.:-
class MagazinesTable extends Table
{
public function initialize(array $config)
{
$this->displayField('name');
}
}
Changing 'name' to the appropriate field.
Alternatively, you can choose which field Cake will use for the values returned by find('list') (this is particularly useful when you want to override the default displayField). E.g.:-
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);
Display selected option in month helper
$this->Form->month('students.month', [
'label' => false,
'value'=>date('m'),
'required'=>true
]);
This actually helped me.
$this->Issues->Magazines->find('list', [
'keyField' => 'id',
'valueField' => 'name'
]);