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
Related
I am using unclead / yii2-multiple-input widget.
I want to generate different number of rows with values from my database.
How can i do this?
I can design my columns in view and edit data manualy after page generated. But miss how to program the number of rows and its values in the view.
My code in view:
<?= $form->field($User, 'User')->widget(MultipleInput::className(), [
'min' => 0,
'max' => 4,
'columns' => [
[
'name' => 'name',
'title' => 'Name',
'type' => 'textInput',
'options' => [
'onchange' => $onchange,
],
],
[
'name' => 'birth',
'type' => \kartik\date\DatePicker::className(),
'title' => 'Birth',
'value' => function($data) {
return $data['day'];
},
'options' => [
'pluginOptions' => [
'format' => 'dd.mm.yyyy',
'todayHighlight' => true
]
]
],
]
])->label(false);
How can I make (for example) 8 rows with different values, and also have the ability to edit/remove/update some of them?
You need to look into the documentation as it says that you need to assign a separate field into the model which will store all the schedule in form of JSON and then provide it back to the field when editing/updating the model.
You have not added the appropriate model to verify how are you creating the field User in your given case above. so, i will try to create a simple example which will help you implement it in your scenario.
For Example.
You have to store a user in the database along with his favorite books.
User
id, name, email
Books
id, name
Create a field/column in you User table with the name schedule of type text, you can write a migration or add manually.
Add it to the rules in the User model as safe.
like below
public function rules() {
return [
....//other rules
[ [ 'schedule'] , 'safe' ]
];
}
Add the widget to the newly created column in ActiveForm
see below code
echo $form->field($model,'schedule')->widget(MultipleInput::class,[
'max' => 4,
'columns' => [
[
'name' => 'book_id',
'type' => 'dropDownList',
'title' => 'Book',
'items' => ArrayHelper::map( Books::find()->asArray()->all (),'id','name'),
],
]
]);
When saving the User model convert the array to JSON string.
like below
if( Yii::$app->request->isPost && $model->load(Yii::$app->request->post()) ){
$model->schedule = \yii\helpers\Json::encode($model->schedule);
$model->save();
}
Override the afterFind() of the User model to covert the json back to the array before loading the form.
like below
public function afterFind() {
parent::afterFind();
$this->schedule = \yii\helpers\Json::decode($this->schedule);
}
Now when saved the schedule field against the current user will have the JSON for the selected rows for the books, as many selected, for example, if I saved three books having ids(1,2,3) then it will have json like below
{
"0": {
"book_id": "1"
},
"2": {
"book_id": "2"
},
"3": {
"book_id": "3"
}
}
The above JSON will be converted to an array in the afterFind() so that the widget loads the saved schedule when you EDIT the record.
Now go to your update page or edit the newly saved model you will see the books loaded automatically.
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 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;
]
I use GridView to show a model called Relatives (familiars of a person) that have two fields: Person (attribute id_person) and Relative (attribute name_relative).
The tables of my database are Persons and Relatives.
I have a problem with the Person field. I don't show the ids of persons, instead I show the names of persons because the id is an auto generated primary key.
When I the user wants to search, it is searched by id_person. I need to search typing a name of a person, nobody will write an id.
Here is the code of the RelativesController file:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
[
'attribute' => 'id_person',
'label' => 'Person',
'value' => function($model) {
$person = \app\models\Persons::findOne(['id_person' => $model->id_person]);
return $person->name_person;
}
],
'name_relative',
],
]); ?>
This is what I have (searching by id):
This is what I need (searching by name):
I would like the export file (expecially XLS) generated by Yii2-export to mimic gridview by exporting all columns in order selected in gridview configuration popup menu.
I mean, lets have two columns A and B. In gridview configuration menu (Little wrench icon) I set that B comes first. My dynagrid output looks like following:
B title| A title
-------|---------
B data | A data
However the export completely ignores this setting and outputs A as first column (because it is defined first in columns array passed as configuration):
A title | B title
---------|----------
A data | B data
In DB, I have table tbl_dynagrid which should contain configuration of gridview. I found corresponding record with id gridview_.
But the content of data column is not changing with reordering columns via gridview configuration.
Is there way how to load (preferably by PHP itself, without JS) order of columns and export to XLS file with that order in mind?
Thank you for help.
Update:
I found out, that gridview is connected to different database. Value of data column in table tbl_gridview is changing as expected after each customization.
This way, I need a way how to translate hashes used in gridview customization menu as column IDs to actual column names or so.
Actual code:
$dataProvider = //..
$pageName = //..
Columns array:
$columns = [
[ 'attribute' => 'col1', 'encodeLabel' => false, 'label' => 'Column A' ],
[ 'attribute' => 'col2', 'encodeLabel' => false, 'label' => 'Column B' ]
];
Export widget:
echo ExportMenu::widget([
'dataProvider' => $dataProvider,
'target'=>ExportMenu::TARGET_SELF,
'showConfirmAlert'=>false,
'container'=>['class'=>'myclass'],
'filename'=>'test',
'columns' => $columns,
'fontAwesome' => true,
'dropdownOptions' => [
'label' => Yii::t('layout','Export'),
'class' => 'btn btn-default'
]]);
And finally dynagrid:
$dynagrid = DynaGrid::begin([
'columns'=>$columns,
'theme'=>'simple-striped',
'showPersonalize'=>true,
'allowThemeSetting'=>false,
'allowFilterSetting'=>false,
'allowSortSetting'=>false,
'toggleButtonGrid'=>['class'=>'toggleButton'],
'gridOptions'=>[
'dataProvider'=>$dataProvider,
'options'=>['class'=>'myid'],
'filterModel'=>$searchModel,
'showPageSummary'=>false,
'floatHeader'=>false,
'pjax'=>false,
'toolbar' => [
['content'=>'{dynagridFilter}{dynagridSort}{dynagrid}'],
'{export}',
]
],
'options'=>['id'=>$pageName]
]);
All I want is to be able to export columns in order selected in gridview, not in the order they are set in $columns array.
The data exported are based on a dataProvider. based on this you should select the column in the .. sequence you need ..
you should build a dataProvider based on a select where you assign each column in the sequence you need ..
$yourDataProvider = YourModel::find()
->select('col1, col2, col3 ... ')
->where( ... )
....