Trying to get property of non-object in action column in yii2 - yii2

I've customized the query in FrameSearch Model and build my query with findbysql. I'm also trying to customize the action column. My gridview looks fine except the action Column.
Getting error -
FrameSearch Model Code -
<?php
namespace frontend\modules\framestock\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\modules\framestock\models\Frame;
use frontend\modules\framestock\models\Poitemframe;
use yii\db\Query;
use yii\db\Command;
/**
* FrameSearch represents the model behind the search form about `frontend\modules\framestock\models\Frame`.
*/
class FrameSearch extends Frame
{
public $purchase;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['f_id'], 'integer'],
[['f_brand', 'f_name','purchase'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$subQuery1 = (new Query())->select(['poi_framename','sum(poi_qty) as purchased'])->from ('poitemframe')->join('LEFT JOIN','Frame','frame.f_name = poitemframe.poi_framename')->groupby('poi_framename');
$subQuery2 = (new Query())->select(['o_frame','count(o_frame) as sold'])->from ('orders')->join('LEFT JOIN','Frame','frame.f_name = orders.o_frame')->groupby('o_frame');
$query = (new Query())->select(['f_brand','f_name','COALESCE(pt.purchased,0)as purchased' , 'COALESCE(st.sold,0) as sold', '(COALESCE(pt.purchased,0) - COALESCE(st.sold,0)) as stock'])->from ('frame')->leftJoin(['pt' => $subQuery1],'pt.poi_framename = frame.f_name')->leftJoin(['st' => $subQuery2],'st.o_frame = frame.f_name');
// ->joinWith(['purchase']);
// $items = $query
// ->select([
// 'f_brand',
// 'f_name',
// 'sum(poitemframe.poi_qty) as purchased',
// ])
// //->where(['stock.product_id'=>3])
// ->groupBy('f_name')
// ->all();
// add conditions that should always apply here
$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;
}
// grid filtering conditions
$query->andFilterWhere([
'f_id' => $this->f_id,
]);
$query->andFilterWhere(['like', 'f_brand', $this->f_brand])
->andFilterWhere(['like', 'f_name', $this->f_name]);
return $dataProvider;
}
}
index.php
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\db\Query;
use yii\db\Command;
/* #var $this yii\web\View */
/* #var $searchModel frontend\modules\framestock\models\FrameSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Frames';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="frame-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'f_brand',
'f_name',
'purchased',
'sold',
'stock',
[
'class' => 'yii\grid\ActionColumn',
'template' => '{ledger}',
'buttons' => [
'ledger' => function ($url, $model) {
return Html::a(
'<span class="glyphicon glyphicon-eye-open"></span>',
['/frame/ledger', 'f_name' => $model->f_name],
[
'title' => 'Ledger',
'data-pjax' => '0',
]
);
},
],
],
],
]); ?>
</div>
update
After adding exit;
Please tell me how to resolve this. I want to get the f_name from the action column button which I'll pass to another page to filter a grid.

I usually recommend to use ArrayHelper::getValue .
For example:
ArrayHelper::getValue($model, 'f_name')
will work when $model is some object (Model or ActiveRecord), array or empty (=null).
Moreover, it has 3nd argument for default value:
ArrayHelper::getValue($model, 'f_name', 'value that returned when attribute not found in $model')

Related

How to show only fix records in the yii2 gridview

I am working with yii2 Framework. I want only few records in gridview where status = 1 in databaseenter image description here
This is the screen shot of gridview I want only highlighted records whose status is 1
This Code of view page is -:
<p>All Issued Devices are Highlighted </p>
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel frontend\models\DeviceTrackerSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
//$this->title = 'Tracked Devices';
//$this->params['breadcrumbs'][] = $this->title;
?>
<b style="font-size: 30px;">ALL ISSUED DEVICES ARE HIGHLIGHTED </b>
<div class="device-tracker-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'rowOptions'=>function($model)
{
if($model->status == '1')
{
return ['class'=>'info'];
}
else
{
return ['class'=>'default'];
}
},
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute'=>'devices_device_id',
'value'=>'devicesDevice.device_name'
],
//'id',
//'devices_device_id',
'user_first_name',
'user_last_name',
'email_address:email',
// 'user_department',
'assign_date',
'return_date',
//'status',
//'Issued_by',
[
'attribute'=>'Issued_by' ,
'value'=>'issuedBy.first_name'
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
Please Tell me how to solve the problem?
Controller action is-
public function actionReturn()
{
// echo "welcome";die;
if(isset(Yii::$app->user->identity->user_type))
{
$status = Yii::$app->user->identity->user_type;
if($status == 1)
{
$this->layout = 'headerLayoutSuperadmin';
$searchModel = new DeviceTrackerSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index1', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
else
{
$this->layout = 'headerLayout';
$searchModel = new DeviceTrackerSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index1', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
}
else
{
return $this->redirect(array('site/login'));
}
}
sql search models-:
<?php
namespace frontend\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\models\DeviceTracker;
/**
* DeviceTrackerSearch represents the model behind the search form about `frontend\models\DeviceTracker`.
*/
class DeviceTrackerSearch extends DeviceTracker
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'status', 'Issued_by'], 'integer'],
[['user_first_name', 'devices_device_id', 'user_last_name', 'email_address', 'user_department', 'assign_date', 'return_date'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = DeviceTracker::find();
//$query = DeviceTracker::findAll('status=>1');
// print_r($query);die;
//echo $query;die;
// add conditions that should always apply here
$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;
}
$query->joinWith('devicesDevice');
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
//'devices_device_id' => $this->devices_device_id,
'assign_date' => $this->assign_date,
'return_date' => $this->return_date,
'status' => $this->status,
'Issued_by' => $this->Issued_by,
]);
$query->andFilterWhere(['like', 'user_first_name', $this->user_first_name])
->andFilterWhere(['like', 'user_last_name', $this->user_last_name])
->andFilterWhere(['like', 'email_address', $this->email_address])
->andFilterWhere(['like', 'user_department', $this->user_department])
->andFilterWhere(['like', 'devices.device_name', $this->devices_device_id]);
return $dataProvider;
}
}
in your search model, update the query to suit the output you want to pass to view.
something like this for the current condition i.e. you want to display only those rows whose status is 1
so,
$query->andFilterWhere([
'id' => $this->id,
//'devices_device_id' => $this->devices_device_id,
'assign_date' => $this->assign_date,
'return_date' => $this->return_date,
'status' => 1, // **this is where you are filtering the data with status == 1**
'Issued_by' => $this->Issued_by,
]);
and brief explanation of flow is
your controller which calls the dataProvider, gives you data that you pass to view and then eventually to gridView
the data is stored in mysql tables, so whatever data you want to send to view you need to query it in the searchModel in dataProvider's query
return dataProvide to controller > view > gridWidget

How to use Json for dataProvider Yii2

Hot to use json for dataProvider for display data in Gridview Yii2?
Here is my Controller (Generate Code from Yii2 generator) code:
<?php
namespace app\controllers;
use Yii;
use app\models\Users;
use app\models\UsersSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* UsersController implements the CRUD actions for Users model.
*/
class UsersController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Users models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new UsersSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Users model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Users model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Users();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Users model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Users model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Users model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Users the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Users::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
And my gridview in index is like this:
<?php
use yii\helpers\Html;
use kartik\grid\GridView;
use yii\widgets\ActiveForm;
use yii\widgets\Pjax;
use yii\web\JsExpression;
/* #var $this yii\web\View */
/* #var $searchModel app\models\SalesOrderSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
?>
<div class="start-stock-index">
<div class="form-group">
<?= Html::a('Create Customer', ['create'], ['class' => 'btn btn-success']) ?>
</div>
<?php Pjax::begin(); ?>
<?= GridView::widget([
'dataProvider'=>$dataProvider,
'filterModel'=>$searchModel,
'showPageSummary'=>true,
'pjax'=>true,
'striped'=>true,
'hover'=>true,
'responsiveWrap' => false,
'panel'=>['type'=>'primary', 'heading'=>$partner_name],
'columns'=>[
[
'attribute' => 'cust_name',
'value' => 'cust_name',
'label' => 'Name',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
[
'attribute' => 'phone_number',
'value' => 'phone_number',
'label' => 'Phone Number',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
[
'attribute' => 'age_type',
'value' => 'ageType.age_name',
'label' => 'Age Category',
'contentOptions' =>
['style'=>'max-width: 100px; font-size: 12px;overflow: auto; word-wrap: break-word;'],
],
['class' => 'kartik\grid\ActionColumn','template' => '{update} {delete}',],
],
]); ?>
<?php Pjax::end(); ?>
</div>
<?php
$script = <<< JS
JS;
$this->registerJs($script);
?>
What I want is show data from json so that it can be restful page. Thanks.
If you JSON structure is right for an arrayDataProvider
You could conver the JSON data in associative array the use the arrayDataprovider
you can use helper as http://www.yiiframework.com/doc-2.0/yii-helpers-json.html
http://www.yiiframework.com/doc-2.0/yii-helpers-basejson.html#decode()-detail
Json::decode($yourJSON);

Getting unknown property error in Yii2

I know there are some answers related to this, but I couldn't find any useful ones.
I am getting this error: Getting unknown property: app\models\Employees::holidays and I've no idea what I'm doing wrong.
Could someone help me out to solve this?
This is my model code:
<?php
namespace app\models;
use Yii;
use yii\data\ActiveDataProvider;
use yii\db\ActiveRecord;
/**
* This is the model class for table "employee".
*
* #property integer $id
* #property string $name
* #property string $surname
* #property string $employment_date
*/
class Employee extends ActiveRecord
{
/** #const SCENARIO_CREATE scenario - create */
const SCENARIO_CREATE = 'create';
/** #const SCENARIO_EDIT scenario - edit */
const SCENARIO_EDIT = 'edit';
/** #const SCENARIO_SEARCH scenario - search */
const SCENARIO_SEARCH = 'search';
/** #const HOLIDAYS_PER_WORK_DAY Earned holidays per one working day. */
const HOLIDAYS_PER_WORK_DAY = 0.4;
/** #var integer $holidays calculated holidays field used in list. */
public $holidays;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'employee';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
// id
['id', 'required', 'except' => self::SCENARIO_SEARCH],
['id', 'integer'],
// name
['name', 'required'],
['name', 'string', 'max' => 255],
// surname
['surname', 'required'],
['surname', 'string', 'max' => 255],
// employment date
['employment_date', 'required'],
['employment_date', 'match',
'pattern' => '/^([1][9]|[2][0])[0-9]{2}[-](0[1-9]|1[0-2])[-](0[1-9]|[1-2][0-9]|3[0-1])$/',
'message' => Yii::t('app',
'Neteisingas datos formatas (Formatas: YYYY-MM-DD)'),
],
['employment_date', 'date',
'format' => 'php:Y-m-d',
'max' => time(),
'tooBig' => Yii::t('app', 'Blogai įvesta data. Vėliausia galima data: ' . date('Y-m-d'))
],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'name' => Yii::t('app', 'Darbuotojo vardas'),
'surname' => Yii::t('app', 'Darbuotojo pavardė'),
'employment_date' => Yii::t('app', 'Įdarbinimo data'),
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
return [
self::SCENARIO_CREATE => [
'name',
'surname',
'employment_date',
],
self::SCENARIO_EDIT => [
'id',
'name',
'surname',
'employment_date',
],
self::SCENARIO_SEARCH => [
'id',
'name',
'surname',
'employment_date',
'holidays',
],
];
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$holidays = 'floor(datediff(curdate(), employment_date) * ' .
Employee::HOLIDAYS_PER_WORK_DAY . ')';
$query = Employees::find()->select([
$this->tableName() . '.id',
$this->tableName() . '.name',
$this->tableName() . '.surname',
$this->tableName() . '.employment_date',
$holidays . ' as holidays',
]);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'defaultOrder' => ['name' => SORT_ASC],
],
]);
$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;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'employment_date' => $this->employment_date,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'surname', $this->surname]);
return $dataProvider;
}
}
My index.php file:
<?php
use app\models\EmployeeSearch;
use yii\data\ActiveDataProvider;
use yii\grid\GridView;
use yii\helpers\Html;
use yii\web\View;
use yii\widgets\Pjax;
/* #var $this View */
/* #var $searchModel EmployeeSearch */
/* #var $dataProvider ActiveDataProvider */
$this->title = Yii::t('app', 'Employees');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="employee-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a(Yii::t('app', 'Create Employee'), ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php Pjax::begin(); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'name',
'surname',
'employment_date',
'holidays',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php Pjax::end(); ?></div>
I know it's a quite long, but I don't know how much of the code I should include.
I think this line holidays in index php file is causing the error.
Add this on your rule .
['holidays', 'integer']
And use this $this->holidays during search.
There is something strange with your code:
My assumption is that you have 2 different models:
"Employee" and "Employees" in your app/models directory.
You are using "Employees" model in the search() of "Employee". For this to work you need to define:
public $holidays;
in your "Employees" model as your error suggests.
But my guess is that you wanted to use maybe "Employee" model for the search(). If this is the case, change the "Employees" to "Employee" in that function:
$query = Employee::find()...
you must comment all your index.php file and run your code. if you have not any error it means error is in index.php page.
then you must uncomment lines one by one and after each uncomment run your project.when you have error it means that line is one of your errors. then keep comment that line and uncomment other one by one and repeat that task to end of file.
in this way you can find your error.
Add the property for holidays in the model before class started:
#property string $holidays
Then it will work.

calculate average in yii2

I am making a cost accounting application.
I want to find the average price over 3 months.
The summary produced in Kartik GridView shows initial share price not the total.
this is my controller
<?php
namespace backend\controllers;
use Yii;
use backend\models\Triwulan;
use backend\models\TriwulanSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* TriwulanController implements the CRUD actions for Triwulan model.
*/
class TriwulanController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Triwulan models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new TriwulanSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Triwulan model.
* #param string $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Triwulan model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Triwulan();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->rm_code]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Triwulan model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param string $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->rm_code]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Triwulan model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param string $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Triwulan model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param string $id
* #return Triwulan the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Triwulan::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
this is my view
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use kartik\grid\GridView;
/* #var $this yii\web\View */
/* #var $model backend\models\Triwulan */
$this->title = $model->rm_code;
$this->params['breadcrumbs'][] = ['label' => 'Triwulans', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="triwulan-view">
<h1><?= Html::encode($this->title) ?></h1>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'rm_code',
'deskripsi_barang',
],
]) ?>
</div>
<?= GridView::widget([
'dataProvider'=>new yii\data\ActiveDataProvider([
'pagination'=>false,
'query'=>$model->getPenerimaans(),
]),
'columns'=>[
['class' => 'kartik\grid\SerialColumn'],
'rm_code',
'bulan',
// 'price',
[
'label' => 'Price',
//'attribute' => 'idDhs.idMatakuliah.jam',
'pageSummary' => true,
// 'pageSummary' => 'Total',
'value' => function ($model) {
if ($model)
return $model->price / 3;
}
],
// ['class' => 'kartik\grid\ActionColumn'],
// 'product',
// 'qty'
],
'showPageSummary' => true,
]) ?>
</div>
Correcting some syntax errors from scaisEdge's answer
public function actionIndex()
{
$searchModel = new TriwulanSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
// calc the average
$myAverage = 0;
$myTot =0;
$myCnt = 0;
foreach ($dataProvider->models as $key => $value) {
$myTot += $value['price'];
$cnt++; // This should be $myCnt
}
if ($cnt>0){ // inside if use $myCnt
$myAverage = myTot/$myCont // here use $myTot/$myCnt
}
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
// render the avegare too
'myAverage' => $myAverage,
]);
}

Filter gridview with select2 widget outside of the grid in yii2

I'm trying to filter gridviews by select2 widget. But the select2 widget should not be within the gridview. It would be like in the screenshot -
And when I select the select2 widget the data is filtered.
My index.php code is -
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;
use frontend\modules\productstockbook\models\Productnames;
use yii\helpers\Json;
/* #var $this yii\web\View */
/* #var $searchModel frontend\modules\productstockbook\models\ProductionSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Product Stock Book';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="production-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?php
echo Select2::widget([
'model' => $model,
'attribute' => 'productnames_productname',
'data' => ArrayHelper::map(Productnames::find()->all(),'productnames_productname','productnames_productname'),
'options' => ['placeholder' => 'Select Product', 'id' => 'catid'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<div class="row-fluid">
<div class="form-group">
<div class="col-xs-3 col-sm-3 col-lg-3" >
<input type="text" class="form-control" id="production" readonly placeholder ="Production">
</div>
<div class="col-xs-3 col-sm-3 col-lg-3" >
<input type="text" class="form-control" id="sell" readonly placeholder ="Sell">
</div>
<div class="col-xs-3 col-sm-3 col-lg-3" >
<input type="text" class="form-control" id="stock" readonly placeholder ="Stock">
</div>
<div class="col-xs-3 col-sm-3 col-lg-3" >
<button type="button" id="search" class="btn btn-primary"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></button>
</div>
</div>
</div>
<div class= 'col-md-6'>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'productionid',
'productiondate',
//'itemid',
'productname',
//'batchno',
'prodqty',
//['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
<div class='col-md-6'>
<?php
echo GridView::widget([
'dataProvider' => $dataProvider2,
'filterModel' => $searchModel2,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'billdate',
'productsales_partyname',
'productname',
'total',
],
]);
?>
</div>
</div>
<?php
/* start getting the textboxes */
$script = <<< JS
$(function(){
//$(document).ready(function(e) { getTotalproduction(); });
$('#catid').change(function(){
getIndexpage();
//getTotalproduction();
//getTotalsell();
//getTotalstock();
});
var catid = $(this).val();
var getIndexpage = function(){
var catid = String($('#catid').val());
window.onbeforeunload = function(e) {return getTotalproduction();};
window.location.href = 'index.php?r=productstockbook/production/index&catid='+catid;
} ;
var getTotalproduction = function(){
var catid = String($('#catid').val());
$.get('index.php?r=productstockbook/production/get-for-production',{ catid : catid }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#production').attr('value',data.totalproduction);
});
} ;
var getTotalsell = function(){
var catid = String($('#catid').val());
$.get('index.php?r=productstockbook/production/get-for-sales',{ catid : catid }, function(data){
//alert(data);
var data = $.parseJSON(data);
$('#sell').attr('value',data.totalsell);
});
};
var getTotalstock = function(){
var totalproduction = parseInt($('#production').val());
var totalsell = parseInt($('#sell').val());
var totalstock = Math.round(totalproduction - totalsell)
//alert(totalstock);
if (isNaN(totalstock) || totalstock < -10000000 || totalstock > 1000000) {
totalstock = '';
}
$('#stock').val(totalstock);
};
// var getTotalstock = function(){
// var catid = String($('#catid').val());
// $.get('index.php?r=productstockbook/production/get-for-stock',{ catid : catid }, function(data){
// alert(data);
// var data = $.parseJSON(data);
// $('#stock').attr('value',data.stock);
// });
// };
});
JS;
$this->registerJs($script);
/* end getting the textboxes */
?>
My Controller code is -
<?php
namespace frontend\modules\productstockbook\controllers;
use Yii;
use frontend\modules\productstockbook\models\Production;
use frontend\modules\productstockbook\models\ProductionSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use frontend\modules\productstockbook\models\ProductsalesSearch;
use yii\helpers\Html;
use frontend\modules\productstockbook\models\Productnames;
use frontend\modules\productstockbook\models\Productsales;
use yii\helpers\Json;
use yii\db\Query;
use yii\db\Command;
/**
* ProductionController implements the CRUD actions for Production model.
*/
class ProductionController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Production models.
* #return mixed
*/
public function actionIndex()
{
$catid = yii::$app->request->get('catid');
$searchModel = new ProductionSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams, $catid);
$searchModel2 = new ProductsalesSearch();
$dataProvider2 = $searchModel2->search(Yii::$app->request->queryParams, $catid);
$model = new Productnames();
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'searchModel2' => $searchModel2,
'dataProvider2' => $dataProvider2,
'model' => $model,
]);
}
/**
* Displays a single Production model.
* #param integer $id
* #return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Production model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Production();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->productionid]);
} else {
return $this->render('create', [
'model' => $model,
]);
}
}
/**
* Updates an existing Production model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->productionid]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
/**
* Deletes an existing Production model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Production model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Production the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Production::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
public function actionGetForProduction($catid)
{
$production = Production::find()->select('sum(prodqty) as totalproduction')->where(['productname'=>$catid])->asArray()->one();
echo Json::encode($production);
}
public function actionGetForSales($catid)
{
$sell = Productsales::find()->select('sum(total) as totalsell')->where(['productname'=>$catid])->asArray()->one();
echo Json::encode($sell);
}
// public function actionGetForStock($catid)
// {
// //$stock = Productsales::find()->joinWith('Production')->select('sum(production.prodqty) - sum(productsales.total) as stock')->where(['productname'=>$catid])->asArray()->one();
// //echo Json::encode($stock);
// //$subQuery1 = (new Query())->select(['productname,sum(prodqty) as totalproduction'])->from('production')->where(['productname'=>$catid]);
// $subQuery2 = (new Query())->select(['productname,sum(total) as totalsell'])->from('productsales')->where(['productname'=>$catid]);
// $subQuery3 = (new Query())->select(['productname,(sum(prodqty) - sell.totalsell) as totalstock'])->from('production')->leftJoin(['sell' => $subQuery2],'sell.productname = productname')->where(['productname'=>$catid]);
// echo Json::encode($subQuery3);
// }
}
ProductionSearch Model code -
<?php
namespace frontend\modules\productstockbook\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\modules\productstockbook\models\Production;
/**
* ProductionSearch represents the model behind the search form about `frontend\modules\productstockbook\models\Production`.
*/
class ProductionSearch extends Production
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['productionid', 'itemid', 'prodqty'], 'integer'],
[['productiondate', 'productname', 'batchno'], 'safe'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params,$catid)
{
$query = Production::find()
//->select(['productionid', 'productiondate', 'itemid', 'productname', 'batchno', 'prodqty'])
->orDerBy([
'productiondate'=>SORT_DESC,
])
->andWhere(['productname' => $catid]);
// add conditions that should always apply here
$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;
}
// grid filtering conditions
$query->andFilterWhere([
'productionid' => $this->productionid,
'productiondate' => $this->productiondate,
'itemid' => $this->itemid,
'prodqty' => $this->prodqty,
]);
$query->andFilterWhere(['like', 'productname', $this->productname])
->andFilterWhere(['like', 'batchno', $this->batchno]);
return $dataProvider;
}
}
ProductsalesSearch Model Code -
<?php
namespace frontend\modules\productstockbook\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\modules\productstockbook\models\Productsales;
/**
* ProductsalesSearch represents the model behind the search form about `frontend\modules\productstockbook\models\Productsales`.
*/
class ProductsalesSearch extends Productsales
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'productsales_ebillid', 'discount'], 'integer'],
[['year', 'console', 'billno', 'billdate', 'productsales_partyname', 'itemid', 'productname', 'batchno', 'expdate', 'productiondate', 'prodqty', 'qty', 'free', 'total'], 'safe'],
[['mrp', 'rate'], 'number'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params,$catid)
{
$query = Productsales::find()
->orDerBy([
'billdate'=>SORT_DESC,
])
->andWhere(['productname' => $catid]);
// add conditions that should always apply here
$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;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'productsales_ebillid' => $this->productsales_ebillid,
'billdate' => $this->billdate,
'expdate' => $this->expdate,
'mrp' => $this->mrp,
'rate' => $this->rate,
'productiondate' => $this->productiondate,
'discount' => $this->discount,
]);
$query->andFilterWhere(['like', 'year', $this->year])
->andFilterWhere(['like', 'console', $this->console])
->andFilterWhere(['like', 'billno', $this->billno])
->andFilterWhere(['like', 'productsales_partyname', $this->productsales_partyname])
->andFilterWhere(['like', 'itemid', $this->itemid])
->andFilterWhere(['like', 'productname', $this->productname])
->andFilterWhere(['like', 'batchno', $this->batchno])
->andFilterWhere(['like', 'prodqty', $this->prodqty])
->andFilterWhere(['like', 'qty', $this->qty])
->andFilterWhere(['like', 'free', $this->free])
->andFilterWhere(['like', 'total', $this->total]);
return $dataProvider;
}
// public function gettotalProduction()
// {
// return $this->c_name.' - '.$this->c_address.' - '.$this->c_mobileno;
// }
}
My point is that in the javascript in index.php file the following code is being used -
window.location.href = 'index.php?r=productstockbook/production/index&catid='+catid;
I don't want the page to be relocated. Because if it relocates I cannot get sum(prodqty) and sum(total) in the textboxes as you can see in the page beaceuse the page is being relocated. How can I achieve this without relocating the page? This is same question as Filter data with kartik Select2 widget in gridview
Update
Currently after working on Edvin's solution - I'm facing the following error -
Since I see it already filters data (but with page reload), I moved to part 2 where you asked for sum of specific column.
I couldn't think of better solution at the moment but this should work for now. Note that it might be only temporary solution because this code is "fragile" (adding an additional column, changing tables' ID, etc.) will break this and you will forced to modify this code. Also please note it takes the sum of all printed rows (meaning only the visible (1st by default) is counted).
I have used something similar before and since IDs are somewhat static, it rarely breaks for me.
$(document).on('ready', function(e) {
var row0 = $('#w0')[0]['childNodes'][2]['childNodes'][2]['children'];
var row1 = $('#w1')[0]['childNodes'][2]['childNodes'][2]['children'];
var total0 = 0;
var total1 = 0;
for (var i = 0; i < row0.length; i++) {
total0 += parseInt(row0[i]['children'][3]['textContent'], 10);
}
for (var i = 0; i < row1.length; i++) {
total1 += parseInt(row1[i]['children'][4]['textContent'], 10);
}
// ^ This number takes (n+1)th column
console.log('First table total value: ' + total0);
console.log('Second table total value: ' + total1);
console.log('Difference between 1st and 2nd total values: ' + (total0 - total1));
})
This will work, assuming your tables' IDs are "w0" (first table) and "w1" (second table) and there are exactly that amount of columns in your represented picture.
In case there are a lot of records, you can increase the size of how many rows to print in table by adding additional lines in Model:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 30,
]
]);