how to get merged array list data in GridView Yii2 - php

Here I have two tables
Employeedetails
Claimprocess
In employeedetails I have 8 columns:
Company_name, Employeecode, Employee_name, father_name, mother_name, wife_name, child1_name, and child2_name.
In Claimprocess table I have 5 columns:
Company_name, Employeecode, Employee_name, Healthcard_no, and claim_for.
In Claimprocess I set a dependent dropdown for employeecode. For example, if admin selects a company_name that automatically shows dependent employeecode, then again admin selects an employeecode that automatically shows the employee_name and employee relations name such as father_name, mother_name, wife_name etc...
This is the dependent dropdown code for employee_code by selecting company_name
claimform.php
<?= $form->field($model, 'company_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Company::find()->all(),'id','companyname'),
'language' => 'en',
'options' => [
'placeholder' => 'Select a company ...',
'onchange' => '
$.post( "index.php?r=employeedetails/lists&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-employee_id" ).html( data );
});',
],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
employeedetailscontroller.php
public function actionLists($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['company_id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['company_id' => $id])
->all();
if($countEmployeedetails>0){
foreach($employeedetails as $employee){
echo "<option value='".$employee->id."'>".$employee->employeecode."</option>";
}
}
else{
echo "<option>-</option>";
}
}
This is dependent dropdown code for employee_name and relations_name by selecting employeecode
claimform.php
<?= $form->field($model, 'employee_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(Employeedetails::find()- >all(),'id','employeecode'),
'language' => 'en',
'options' => [
'placeholder' => 'Select a employeecode ...',
'onchange' => '
$.post( "index.php?r=employeedetails/lists2&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-claim_for" ).html( data );
}),
$.post( "index.php?r=employeedetails/lists1&id='.'"+$(this).val(), function( data ) {
$( "select#claimprocess-employee_name" ).html( data );
});',
],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
employeedetailscontroller.php
public function actionLists1($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['id' => $id])
->all();
if($countEmployeedetails >= 0)
{
foreach($employeedetails as $employee)
{
echo "<option value='".$employee->id."'>".$employee->name."</option>";
}
}
else{
echo "<option>-</option>";
}
}
public function actionLists2($id)
{
$countEmployeedetails = Employeedetails::find()
->where(['id' => $id])
->count();
$employeedetails = Employeedetails::find()
->where(['id' => $id])
->all();
if($countEmployeedetails >= 0)
{
foreach($employeedetails as $employee)
{
echo "<option value='".$employee->id."'>".$employee->father_name."</option>";
echo "<option value='".$employee->id."'>".$employee->mother_name."</option>";
echo "<option value='".$employee->id."'>".$employee->wife_name."</option>";
echo "<option value='".$employee->id."'>".$employee->child1_name."</option>";
echo "<option value='".$employee->id."'>".$employee->child2_name."</option>";
}
}
else{
echo "<option>-</option>";
}
}
In claim_for field I have to select relation names of the particular employee, so what I did is combine all relation fields such as father_name, mother_name etc using array_merge and I got a name in form.
claimform.php
<?php
$em = ArrayHelper::map(Employeedetails::find()- >all(),'id','father_name');
$emp = ArrayHelper::map(Employeedetails::find()->all(),'id','mother_name');
$emp1 = ArrayHelper::map(Employeedetails::find()->all(),'id','wife_name');
$emp2 = ArrayHelper::map(Employeedetails::find()->all(),'id','child1_name');
$emp3 = ArrayHelper::map(Employeedetails::find()->all(),'id','child2_name');
$print = array_merge($em,$emp,$emp1,$emp2,$emp3);
// echo "<pre>";print_r($print);exit();echo "</pre>";
echo $form->field($model, 'claim_for')->dropDownList($print,['option' => '']);
?>
The problem:
While selecting relation I am getting all the relations name in the form, but while saving it in gridview I am getting employee_id instead of merge_array id.
So here I used this code to get relation name, but I dont know whether my write code is right or wrong:
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'id',
'company.companyname',
'employee.employeecode',
'employee.name',
'claim_for',
[
'attribute' => 'claim_for',
'format' => 'raw',
'value' => function($model, $key, $index, $grid) {
$temp = $model->claim_for;
$si = Employeedetails::find()->where(['id' => $temp])->one();
return $si['father_name'];// here how to bring merged array relation name
},
],
'healthcard_no',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
I've been searching for two days but am not able to get it. If anyone can help, I'd appreciate it.

create field in claimprocess table as claim_for and store the getting value from employeedetails in seperate table. thats it, Hope it will you
claimprocesscontroller.php
$commaList = explode('-', $model->claim_for);
$model->claimer_name = $commaList[1];
employeedetails.php
echo "<option value='".$employee->id. '-' .$employee->name. "'>".$employee-RelationName7."</option>";

Related

CakePHP 3.6: Update control value based on the selection of a dropdown control

I have the following tables:
customers[id, name, surname, phone, text, balance, created]
service_types[id, title, price, length, is_subscription, created, payment]
customer_service_types[id, customer_id, service_type_id, price, created]
And the relations:
ServiceTypesTable.php:
$this->hasMany('CustomerServiceTypes', [
'foreignKey' => 'service_type_id'
]);
CustomerServiceTypesTable.php:
$this->belongsTo('Customers', [
'foreignKey' => 'customer_id',
'joinType' => 'INNER'
]);
$this->belongsTo('ServiceTypes', [
'foreignKey' => 'service_type_id',
'joinType' => 'INNER'
]);
In CustomerServiceTypes\add.ctp I have a dropdown with the services and a field for the price:
echo $this->Form->control('customer_id', ['options' => $customers,'label' => 'Customer']);
echo $this->Form->control('service_type_id', ['options' => $serviceTypes, 'label' => 'Service']);
echo $this->Form->control('price', ['label' => 'Price']);
In the CustomerServiceTypesController.php:
public function add($customerid = null)
{
$customerServiceType = $this->CustomerServiceTypes->newEntity();
if ($this->request->is('post')) {
$customerServiceType = $this->CustomerServiceTypes->patchEntity($customerServiceType, $this->request->getData());
if ($this->CustomerServiceTypes->save($customerServiceType)) {
//debug($this->request->getData("customer_id"),true);
$this->Flash->success(__('Success'));
return $this->redirect(['controller' => 'customers', 'action' => 'edit', $customerid]);
}
$this->Flash->error(__('Fail'));
}
$customers = $this->CustomerServiceTypes->Customers->find('list', ['limit' => 200])->where(['Customers.id =' => $customerid]);
$serviceTypes = $this->CustomerServiceTypes->ServiceTypes->find('list', [
'valueField' => function ($row) {
return $row['title'] . ' (Suggested price: ' . $row['price'] . ')';
}
], ['limit' => 200]);
$this->set(compact('customerServiceType', 'customers', 'serviceTypes'));
}
Which adds in the services dropdown valuefield the value of the specific service:
Service_1 (Suggested price: 100)
Service_2 (Suggested price: 150)
.....
But what I want to achieve is to update the price field with the suggested price when user makes a selection in the dropdown field. Is it possible to achieve that server side? Without the use of javascript? Because my knowledge is very limited in javascript. If not can you provide a working example based on my question?
Make Following changes:
add.ctp
<div ng-app="" ng-init='servicePrices = <?php echo json_encode($servicePrices); ?>;' >
<?php
echo $this->Form->create();
echo $this->Form->control('customer_id', ['options' => $customers,'label' => 'Customer']);
echo $this->Form->control('service_type_id', [
'options' => $serviceTypes, 'label' => 'Service',
'ng-model'=>'service_type_id'
]);
echo $this->Form->control('price', [
'label' => 'Price',
'ng-model'=>'servicePrices[service_type_id]'
]);
echo $this->Form->submit('submit');
?>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js" ></script>
CustomerServiceTypesController.php
// add this
$servicePrices = $this->CustomerServiceTypes
->ServiceTypes
->find()
->limit(200)
->combine('id','price');
$this->set(compact('customerServiceType', 'customers', 'serviceTypes','servicePrices'));

Yii2 - Removing an item from the dropDownList

In my ticket form I have a dropDownList for the employees, and in the employees model I have employee_status which is 'Available', 'Not Available'
If I change the status of the employee to 'Not Available' how am I going to remove it automatically from the dropDownList in Ticket form?
The Employee Dropdown from Ticket
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>
You need to create a dependent dropdown for get employee list according to employee_status.Write down below code in view file for creating dependent dropdown :-
use yii\helpers\ArrayHelper;
echo $form->field($model, 'employee_status')->dropDownList([0=>'Available' , 1 => 'Not Available'],
[
'prompt' => 'Select Employee Status',
'style' => 'width:200px',
'onchange'=>'$.post( "'.Yii::$app->urlManager->createUrl('site/get-employee?status=').'"+$(this).val(), function( data ) {
$( "select#employee-employee_id" ).html( data );
});']);
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>
Now write a controller action for get data for child dropdown. Controller action code like below :-
SiteController.php
public function actionGetEmployee($status)
{
$employee= \common\models\Employee::find()
->where(['status' => $status])
->orderBy('id DESC')
->all();
if (!empty($employee)) {
foreach($employee as $employee) {
echo "<option value='".$employee->id."'>".$employee->name."</option>";
}
} else {
echo "<option>-</option>";
}
}
Note : change the model namespace according to your code.
Perform a find query with your given criteria.
Since we only ever want available employees in our list, we can write:
Employee::find('status=:status', [
':status' => 'Available'
])->all();
I finally get it
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->where(['status' => 'Available'])->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>

Yii2 : kartik Select2

I have 2 select2 dropdownlist the second depends on data from the first one
the first one code :
<?= $form->field($model, 'patient_id')->widget(select2::className(),[
'data'=> arrayhelper::map(patient::find()->all(),'patient_id','patient_name'),
'options'=>['placeholder'=>'select patient Name ... '],
'pluginOptions'=>[
'allowClear'=>true
],
])?>
the second one code :
<?= $form->field($model, 'doctor_id')->widget(select2::className(),[
'data'=> arrayhelper::map(doctors::find()->all(),'doctor_id','doctor_name'),
'options'=>['placeholder'=>'أختر اسم الطبيب '],
'pluginOptions'=>[
'allowClear'=>true
],
])?>
i know the sql code in the second one is :
select doctor_name from doctors
so i need it to be :
SELECT DISTINCT doctor_name from doctors where doctor_id in (SELECT doctor_id from patient_services WHERE patient_id="THE VALUE FROM THE 1st DROPDOWNLIST" )
in the regular dropdownlist it work by like this way Yii2 Lesson - 20 Dependent Drop Down Lists By DoingITeasyChannel but in select2 i didn't find how to do it .
------------------------------- after update ----
as the comments there is DepDrop but i got confused how to use it.
i've changed
<?= $form->field($model, 'patient_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(patient::find()->asArray()->all(), 'patient_id', 'patient_name')]);
?>
and the other one is :
<?= $form->field($model, 'doctor_id')->widget(DepDrop::classname(), [
'options' => ['placeholder' => 'Select ...'],
'type' => DepDrop::TYPE_SELECT2,
'select2Options'=>['pluginOptions'=>['allowClear'=>true]],
'pluginOptions'=>[
'depends'=>['receipts-doctor_id'], // here i got confused
'url' => Url::to(['/receipts/child']),
'loadingText' => 'Loading child level 1 ...',
]
]);
?>
in controller
public function actionChild() {
$out = [];
if (isset($_POST['depdrop_parents'])) { // what they meaning by depdrop_parents or what i should change it ?
$id = end($_POST['depdrop_parents']);
$list = Account::find()->andWhere(['parent'=>$id])->asArray()->all();
$selected = null;
if ($id != null && count($list) > 0) {
$selected = '';
foreach ($list as $i => $account) {
$out[] = ['id' => $account['id'], 'name' => $account['name']];
if ($i == 0) {
$selected = $account['id'];
}
}
// Shows how you can preselect a value
echo Json::encode(['output' => $out, 'selected'=>$selected]);
return;
}
}
echo Json::encode(['output' => '', 'selected'=>'']);
}
First field (Select2):
<?= $form->field($model, 'patient_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(patient::find()->asArray()->all(), 'patient_id', 'patient_name')]);
?>
Second field (DepDrop):
<?= $form->field($model, 'doctor_id')->widget(DepDrop::classname(), [
'options' => ['placeholder' => 'Select ...'],
'type' => DepDrop::TYPE_SELECT2,
'select2Options'=> ['pluginOptions' => ['allowClear' => true]],
'pluginOptions'=> [
'depends' => ['receipts-doctor_id'],
'url' => Url::to(['/receipts/child']),
'loadingText' => 'Loading child level 1 ...',
]
]);
?>
Plugin option 'depends' => ['receipts-doctor_id'], shows which element (takes element's ID) must be changed (on click, on select, etc.) in order to send Ajax request and retrieve results from controller. In this case, an element with ID receipts-doctor_id should be present. If you don't know or you want to set ID for parent element, you can use 'options' => ['id' => 'receipts-doctor_id'], for your parent element.
And for controller, you can retrieve value like this:
public function actionChild()
{
$depdropParents = Yii::$app->request->post('depdrop_parents');
if ($depdropParents !== null) {
$value = $depdropParents[0];
// Now your $value contains what was being selected in parent element
}
}

Assigning function to value attribute in details view yii2 [duplicate]

This question already has answers here:
Changing value of an attribute in DetailView widget
(2 answers)
Closed 6 years ago.
I am trying to assign a value of a function to 'value' in DetailView. But when I try that I get the error "Object of class Closure could not be converted to string"
I tried returning the value of the function by assigning it to another variable too but still the same error.
Can someone help me figure it out please?
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'Task_ID',
'Task_Title',
'Description',
'projects.project_name', //display project name instead of project id
// 'Assign_task_to',
//'tasksemp.Employee_ID',
[
'attribute' => 'Assign_task_to',
'format' => 'raw',
$data = function ($model) {
$assignEmpModel = Tasksemp::find()->where(['Task_ID' => $model->Task_ID])->all(); //get all the rows with teh same task_id
$employes = ''; //empty string
foreach ( $assignEmpModel as $employee ) {
$emp = Employee::find()->where(['Employee_ID'=>$employee->Employee_ID])->one(); //get all the employee_id
$name = $emp['employee_name']; //get the employee_name from the employees table
$employes .= ' '.$name.', '; //concatenate the names.
}
// return implode(', ',$employes);
//return $employes;
},
'value' => $data,
],
'start_date',
'due_date',
'priotiy_level',
'upload_documents',
],
]) ?>
I have tried assigning the function to a variable $data but doesn't work.
I have tried assigning the function directly to the value as well but same error.
[
'attribute' => 'Assign_task_to',
'format' => 'raw',
'value' => function ($model) { //<----- ERROR HERE!
$assignEmpModel = Tasksemp::find()->where(['Task_ID' => $model->Task_ID])->all(); //get all the rows with teh same task_id
$employes = ''; //empty string
foreach ( $assignEmpModel as $employee ) {
$emp = Employee::find()->where(['Employee_ID'=>$employee->Employee_ID])->one(); //get all the employee_id
$name = $emp['employee_name']; //get the employee_name from the employees table
$employes .= ' '.$name.', '; //concatenate the names.
}
return $employes;
},
],
Tried Bizley's solution like this:
<?php $assignEmpModel = Tasksemp::find()->where(['Task_ID' => $model->Task_ID])->all(); //get all the rows with teh same task_id
$employes = ''; //empty string
foreach ( $assignEmpModel as $employee ) {
$emp = Employee::find()->where(['Employee_ID'=>$employee->Employee_ID])->one(); //get all the employee_id
$name = $emp['employee_name']; //get the employee_name from the employees table
$employes .= ' '.$name.', '; //concatenate the names.
?>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'Task_ID',
'Task_Title',
'Description',
'projects.project_name', //display project name instead of project id
// 'Assign_task_to',
//'tasksemp.Employee_ID',
[
'attribute' => 'Assign_task_to',
'format' => 'raw',
'value' => $employes,
],
'start_date',
'due_date',
'priotiy_level',
'upload_documents',
],
]) ?>
But now the error says unexpected end of file.
DetailView doesn't allow closure for the value because there is no need for it since DetailView operates on single model (doesn't iterate on many models like GridView).
Your first approach is totally bad because you try to push some code between the array elements. Second approach is ok but no closure allowed here.
Simply just take the code that is the body of your function ($model) (of course without the return part) and put it above the <?= DetailView::widget(... and then use the $employes variable for the value inside.
[
'attribute' => 'Assign_task_to',
'format' => 'raw',
'value' => $employes,
],
You can use custom functions to get a value in DetailView.
Use call_user_func() to achieve this:
<?= \yii\widgets\DetailView::widget([
'model' => $yourModel,
'attributes' => [
[
'label' => 'Your label',
'value' => call_user_func(function ($model) {
// do what you like
// return your value;
}, $yourModel),
],
// more attributes
]
]); ?>

Yii2: How to have sum in footer based on previous pages' sum?

Please look the picture below.
As you can see total is 215340 in the summary column. What I want is that in the next page it should start summing those numbers on this number.
Here is a code.
GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
[
'class' => 'kartik\grid\SerialColumn'],
// 'id',
[
'attribute' => 'customer_id',
'value' => function ($data) {
return $data->customerDetail->account_no;
}
],
[
'attribute' => 'naration',
'pageSummary' => 'Total',
],
[
'attribute' => 'transaction_type',
'label' => 'Deposits',
'pageSummary' => true,
'pageSummaryOptions' => ['id' => 'total_sum'],
'value' => function ($data) {
if($data->transaction_type==10)
return $data->amount;
else
return 0;
}
],
[
'attribute' => 'transaction_type',
'label' => 'Withdrawals',
'pageSummary' => true,
'value' => function ($data) {
if($data->transaction_type==11)
return $data->amount;
else
return 0;
}
],
[
'class' => 'backend\components\TotalColumn',
'label' => 'Balance',
'attribute' =>'amount',
],
],
// This line displays sum of the columns.
'showPageSummary' => true,
]);
?>
I was thinking about sending this page's sum to the next page using $_GET but the problem is when user going to previous pages i.e. from page 3 to 2. Do you any widget or something for this problem?
My idea is using mysql to select sum of all records in the current column and add this value with the total value of the previous page, I need to know offset and limit of the current page for this query, I can get those values from data provider, to achieve this I have to override the function \yii\grid\Column::renderFooterCellContent().
Extend \yii\grid\DataColumn class
namespace frontend\components;
use yii\helpers\ArrayHelper;
class DataColumn extends \yii\grid\DataColumn
{
protected function renderFooterCellContent()
{
if ($this->footer instanceof \Closure) {
return call_user_func($this->footer, ArrayHelper::getValue($this, 'grid.dataProvider.pagination'));
} else {
return parent::renderFooterCellContent();
}
}
}
Your view file
use frontend\models\Client;
use yii\db\Expression;
use yii\db\Query;
use yii\grid\GridView;
use yii\data\Pagination;
use frontend\components\DataColumn;
echo GridView::widget([
'dataProvider' => $dataProvider,
'dataColumnClass' => DataColumn::className(),
'showFooter' => true,
'columns' => [
//['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'num_users',
'footer' => function ($pagination) {
if ($pagination instanceof Pagination) {
$offset = $pagination->offset;
$limit = $pagination->limit;
$cquery = (new Query())
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'cpage' => (new Query())
->select('num_users')
->offset($offset)
->limit($limit)
->from(Client::tableName())
]);
//negative offset is illegal
if ($offset > 0) {
$pquery = (new Query())
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'ppage' => (new Query())
->select('num_users')
->offset(0)
->limit($offset)
->from(Client::tableName())
]);
$cquery->union($pquery, true);
}
return (new Query())->from(['subt' => $cquery])->sum('sub_users');
}
}
],
]
]);
Raw SQL query
SELECT SUM(sub_sum_users) FROM (
SELECT SUM(num_users) as sub_sum_users FROM (
SELECT num_users FROM `clients` LIMIT 20 OFFSET 120
) cpage
UNION ALL
SELECT SUM(num_users) as sub_sum_users FROM (
SELECT num_users FROM `clients` LIMIT 20 OFFSET 100
) ppage
) sublt
Note:
You could consider to use ActiveRecord, my girdview has a lot of join queries so it's very heavy for me
$offset = $pagination->offset;
$limit = $pagination->limit;
$cquery = Client::find()
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'cpage' => Client::find()->select('num_users')->offset($offset)->limit($limit)
]);
//negative offset is illegal
if ($offset > 0) {
$pquery = $cquery = Client::find()
->select(['sub_users' => new Expression('SUM(num_users)')])
->from([
'ppage' => Client::find()->select('num_users')->offset(0)->limit($offset)
]);
$cquery->union($pquery, true);
}
return (new Query())->from(['subt' => $cquery])->sum('sub_users');

Categories