Issue for a "two dimentionnal 'add another item' " with FormStateInterface::getTriggeringElement() - programmatically-created

I'm learning drupal 8. I want create a page who contain a 'two dimensionnal' 'add another item' form. My code works well almost, but I have a strange behavior when I add rooms to a house (there is a strange value in my debug logs from the FormStateInterface::getTriggeringElement(), see to the bottom for the code and log)
First : I have two structures, houses and rooms. The user can create some houses and for each house, he can create some rooms :
When I add some houses, the form works fine :
When I add some rooms to the last house, the form works fine too :
But when I add some rooms to any "no-last" house, the form doesn't work fine (in the screenshot, I click one time to the "add room" in the block house '1', the label of the "house 1" became "house 2" (?!) and on click add 5 rooms (?!) :
Here my code and a strange debug log, I don't explain why I get this value (from the getTriggeringElement() in the room_addMoreSubmit callback and this is the problem I think)
<?php
namespace Drupal\projet\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
class HouseForm extends FormBase {
public function getFormId(){
return 'custom_rooms_form';
}
function buildForm(array $form, FormStateInterface $form_state) {
$house_count = $form_state->get('house_count');
if (is_null($house_count)) {
$house_count = 1;
$form_state->set('house_count', $house_count);
}
$form['house'] = array(
//'#tree' => TRUE,
'#prefix' => '<div id="house-replace">',
'#suffix' => '</div>'
);
for ($house_delta = 0; $house_delta < $house_count; $house_delta++) {
if (!isset($form['house'][$house_delta])) {
$room_count[$house_delta] = $form_state->get('room_count_'.$house_delta);
if (is_null($room_count[$house_delta])) {
$room_count[$house_delta] = 1;
$form_state->set('room_count_'.$house_delta, $room_count[$house_delta]);
}
dd($room_count, "room_COUNT");
$form['house'][$house_delta]['room'] = array(
'#type' => 'fieldset',
'#title' => t('house : '.$house_delta),
//'#tree' => TRUE,
'#prefix' => '<div id="room-replace-'.$house_delta.'">',
'#suffix' => '</div>'
);
for ($room_delta = 0; $room_delta < $room_count[$house_delta]; $room_delta++) {
if (!isset($form['house'][$house_delta]['room'][$room_delta])) {
$room = array(
'#type' => 'textfield'
);
$check = array(
'#type' => 'checkbox'
);
$form['house'][$house_delta]['room'][$room_delta] = array(
'#type' => 'fieldset',
'#title' => t('room : '.$house_delta.'.'.$room_delta),
);
$form['house'][$house_delta]['room'][$room_delta]['text'] = $room;
$form['house'][$house_delta]['room'][$room_delta]['check'] = $check;
}
}
$form['house'][$house_delta]['room']['add'] = array(
'#type' => 'submit',
'#name' => 'add',
'#value' => t('Add room'),
'#attributes' => array('class' => array('field-add-more-submit'), 'house_delta' => array($house_delta)),
'#submit' => array(array(get_class($this), 'room_addMoreSubmit')),
'#ajax' => array(
'callback' => array($this, 'room_addMoreCallback'),
'wrapper' => 'room-replace-'.$house_delta,
'effect' => 'fade',
),
);
}
}
$form['house']['add'] = array(
'#type' => 'submit',
'#name' => 'add',
'#value' => t('Add house'),
'#attributes' => array('class' => array('field-add-more-submit')),
'#submit' => array(array(get_class($this), 'house_addMoreSubmit')),
'#ajax' => array(
'callback' => array($this, 'house_addMoreCallback'),
'wrapper' => 'house-replace',
'effect' => 'fade',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Create'),
);
return $form;
}
public function room_addMoreSubmit(array $form, FormStateInterface $form_state) {
dd($form_state->getTriggeringElement(), "room : getTriggeringElement()"); // below, the log when I add a room to the house '1' (result see above with the last screenshot: "the house 1" became "house 2" and one click add 5 rooms)
$house = $form_state->getTriggeringElement()["#array_parents"][1];
$c = $form_state->get('room_count_'.$house) + 1;
$form_state->set('room_count_'.$house, $c);
$form_state->setRebuild(TRUE);
}
public function room_addMoreCallback(array $form, FormStateInterface $form_state) {
$house = $form_state->getTriggeringElement()["#array_parents"][1];
return $form['house'][$house]['room'];
}
public function house_addMoreSubmit(array $form, FormStateInterface $form_state) {
dd($form_state->getTriggeringElement()["#array_parents"], "house : getTriggeringElement()");
$c = $form_state->get('house_count') + 1;
$form_state->set('house_count', $c);
$form_state->setRebuild(TRUE);
}
public function house_addMoreCallback(array $form, FormStateInterface $form_state) {
return $form['house'];
}
}
The log ('dd' in the room_addMoreSubmit) when I click on the "add room" button in the house "1":
When I click on the "add room" button in the house number 1, getTriggeringElement return the array parents of the add button. And, as you can see, the parent is "2" not "1" (the house 1)
So when I click on the "add room" button of the house 1, this is the house "2" which is identified and not the house "1".
I don't understand why...Use the getTriggeringElement is not the good way ?

The solution :
$form['house'][$house_delta]['room']['add'] = array(
'#type' => 'submit',
'#name' => 'add-'.$house_delta,
'#value' => t('Add room'),
'#attributes' => array('class' => array('field-add-more-submit'), 'house_delta' => array($house_delta)),
'#submit' => array(array(get_class($this), 'room_addMoreSubmit')),
'#ajax' => array(
'callback' => array($this, 'room_addMoreCallback'),
'wrapper' => 'room-replace-'.$house_delta,
'effect' => 'fade',
),
);
The unique name was the issue of my problem. So, I change the name attribute.

Related

How to make all cells wrap text and have complete all borders in Laravel Excel

I want to make export results with Laravel Excel, but the results did not match what I wanted.
what I want is like this
I want all cells to be wrapped in text and have a complete border.
This is my code:
class SdgsExportView2 implements FromView, WithTitle {
protected $id_perangkat_daerah;
function __construct($id_perangkat_daerah) {
$this->id_perangkat_daerah = $id_perangkat_daerah;
}
public function view(): View
{
$data_sdgs = DataSdgs::where('id_perangkat_daerah',$this->id_perangkat_daerah)
->with('indikator.target.sdgs')
->with('detail_data_sdgs.kegiatan.program.perangkat_daerah')
->get();
return view('template.exportMatrik2', [
'data_sdgs' => $data_sdgs
]);
}
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$cellRange = 'A1:W100'; // All headers
$event->sheet->getDelegate()->getStyle($cellRange)->getFont()->setSize(14);
$event->sheet->getDelegate()->getStyle($cellRange)->getAlignment()->setWrapText(true);
}
];
}
public function title() : string
{
return 'MATRIK 2';
}
}
I really hope for your help
I know it is a bit late to answer (after 8 months), but to add border format to your code is relatively simple.
In your event function AfterSheet::class => function(AfterSheet $event) you need to add following code:
$styleHeader = [
'borders' => [
'allBorders' => [
'borderStyle' => 'thin',
'color' => ['rgb' => '808080']
],
]
];
$event->sheet->getStyle("A1:C1")->applyFromArray($styleHeader);
And replace "A1:C1" with your header range.
For me I have added event by extends WithEvents and use
use Maatwebsite\Excel\Concerns\WithEvents;
Then I apply like this....
public function registerEvents(): array
{
$alphabetRange = range('A', 'Z');
$alphabet = $alphabetRange[$this->totalValue+6]; // returns Alphabet
$totalRow = (count($this->attributeSets) * 3) + count($this->allItems)+1;
$cellRange = 'A1:'.$alphabet.$totalRow;
return [
AfterSheet::class => function(AfterSheet $event) use($cellRange) {
$event->sheet->getStyle($cellRange)->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
'color' => ['argb' => '000000'],
],
],
])->getAlignment()->setWrapText(true);
},
];
}
For Details or more you can follow The doc https://docs.laravel-excel.com/3.1/getting-started/
#Zahid answer little bit update for v3.1
public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$alphabet = $event->sheet->getHighestDataColumn();
$totalRow = $event->sheet->getHighestDataRow();
$cellRange = 'A7:'.$alphabet.$totalRow;
$event->sheet->getStyle($cellRange)->applyFromArray([
'borders' => [
'allBorders' => [
'borderStyle' => Border::BORDER_HAIR,
],
],
])->getAlignment()->setWrapText(true);
},
];
}
I think this might help you what you looking for : phpspreadsheet simpler
There is a method
// $titleName : pass data that you wants to set (not array)
// $mergeTill : pass count of array dataset (Int)
public function setTitle($titleName, $mergeTill, $startCell ,$styleName = "")
go through this example given link

Yii2-Use SqlDataProvider with GridView and enable Gridview Filter for search

I am working on yii2. I have a custom view in which I have placed to views DetailView and GridView. Below is my controller code
public function actionViewcreated($id)// passed the id of my model which is created in the previous step
{
$model=$this->findModel($id); // this will find my model/record based on the id
$sub_div = $model->sub_div;
$meter_type = $model->meter_type;
$query = "SELECT DISTINCT m.`id` AS meter_id, ins.`meter_msn` AS Meter_Serial_Number, ins.`meter_type` AS Meter_Type, sd.`sub_div_code` AS Sub_Division_Code,sd.`name` AS Sub_Division_Name
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` = map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` = sd.`sub_div_code`
WHERE ins.`meter_type` = '$meter_type'
AND sd.`sub_div_code` = '$sub_div'
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM
`meter_acceptance_details` md WHERE md.`flag` IN (1))";
$session = Yii::$app->session;
$session->set('my_sql', $query);
$count = Yii::$app->db->createCommand("SELECT COUNT(DISTINCT m.`id`)
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` = map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` = sd.`sub_div_code`
WHERE ins.`meter_type` = '$meter_type'
AND sd.`sub_div_code` = '$sub_div'
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM `meter_acceptance_details` md WHERE md.`flag` IN (1))")->queryScalar();
$session = Yii::$app->session;
$session->set('total', $count);
if($count <= 0)
{
$this->findModel($id)->delete();
\Yii::$app->getSession()->setFlash('errors', '
<div class="alert alert-error alert-dismissable">
<button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
<strong>There are no meters installed against the selected Sub Division!!!! </strong>Acceptance is not Created</div>');
return $this->redirect(['index', 'id' => $model->id]);
}
else
{
$dataProvider = new SqlDataProvider([
'sql' => $query,
'totalCount' => $count,
'pagination' => [
'pageSize' => 40,
],
]);
return $this->render('viewcreated', [
'dataProvider' => $dataProvider,
'model' => $model,
'id' => $model->id
/*'searchModel' => $searchModel*/
]);
}
}
View
<?php Pjax::begin(); ?>
<?= DetailView::widget([
'model' => $model,
'attributes' => [
[
'label'=>'Serial #',
'value' => function($d)
{
return $d->id;
}
],
[
'label' => 'Meter Type',
'value' => function ($d) {
if(is_object($d))
return $d->meter_type;
return ' - ';
},
],
'sub_div',
[
'label' => 'Sub Division Name',
'value' => function ($d) {
if(is_object($d))
return $d->subDiv->name;
return '-';
},
],
[
'label' => 'Prepared By',
'value' => function ($d) {
if(is_object($d))
return $d->prepared->name;
},
],
'prepared_at',
'status',
],
]) ?>
<br>
<?= GridView::widget([
'dataProvider' => $dataProvider,
/*'filterModel' => $searchModel,*/
'id'=>'gv',
'columns' => [
['class' => 'yii\grid\SerialColumn'],
['class' => 'yii\grid\CheckboxColumn', 'checkboxOptions' => function($d) {
return ['value' => $d['meter_id']];
}],
'Meter_Serial_Number',
'Meter_Type',
'Sub_Division_Code',
'Sub_Division_Name',
],
]); ?>
<?php Pjax::end(); ?>
JS
$("#chk input:checkbox").prop("checked", true);
Output
In the above grid view I want to add search column for Meter Serial Number and dropdown for Sub Division Name.
Update 1
Installation Model
class Installations extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'installations';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['created_at', 'updated_at','imsi_no','old_meter_power','old_meter_reactive_power','new_meter_power','new_meter_reactive_power','ct_ratio','ct_ratio_quantity','cable_length','cable_type','atb_installed'], 'safe'],
[['created_by', 'updated_by', 'status'], 'integer'],
[['ref_no', 'meter_msn', 'billing_msn', 'customer_id','ct_ratio_quantity','cable_length','meter_type'], 'string', 'max' => 50],
[['tarrif', 's_load', 'ct_ratio','cable_type'], 'string', 'max' => 100],
[['latitude', 'longitude'], 'string', 'max' => 11],
[['site_issues', 'istallation_status', 'comm_status'], 'string', 'max' => 200],
[['consumer_name', 'consumer_address'], 'string', 'max' => 255],
[['so_person_name'], 'string', 'max' => 40],
[['so_phone_number', 'so_person_designation','atb_installed'], 'string', 'max' => 20],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'ref_no' => 'Ref No',
'meter_msn' => 'Meter MSN',
'billing_msn' => 'Billing MSN',
'tarrif' => 'Tarrif',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
'status' => 'Status',
'latitude' => 'Latitude',
'longitude' => 'Longitude',
'site_issues' => 'Site Issues',
'istallation_status' => 'Installation Status',
'comm_status' => 'Comm Status',
'customer_id' => 'Customer ID',
'consumer_name' => 'Consumer Name',
'consumer_address' => 'Consumer Address',
's_load' => 'Sanctioned Load',
'so_person_name' => 'Person Name',
'so_phone_number' => 'Phone Number',
'so_person_designation' => 'Person Designation',
'imsi_no' => 'IMSI #',
'old_meter_power' => 'Old Meter Power (kWh)',
'old_meter_reactive_power' => 'Old Meter Reactive Power (kVArh)',
'new_meter_power' => 'New Meter Power (kWh)',
'new_meter_reactive_power'=>' New Meter Reactive Power (kVArh)',
'ct_ratio'=>'CT Ratio',
'ct_ratio_quantity'=>'CT Ratio Quantity',
'cable_length'=>'Cable Length',
'cable_type'=>'Cable Type',
'atb_installed'=>'ATB Installed',
'meter_type'=>'Meter Type',
];
}
public static function getCommStatus()
{
return [
//'' => 'Please Select',
'Verified' => 'Verified',
'Failed' => 'Failed',
'System Verified' => 'System Verified'
//'Return Communication Failed SIM' => 'Return Communication Failed SIM'
];
}
public static function getInstallStatus()
{
return [
//'' => 'Please Select',
'Installed' => 'Installed',
'Not Installed' => 'Not Installed',
'System Installed'=>'System Installed'
//'Return Communication Failed SIM' => 'Return Communication Failed SIM'
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getInstallationImages()
{
return $this->hasMany(InstallationImages::className(), ['installation_id' => 'id']);
}
public function getImages(){
return InstallationImages::find()->where(['installation_id' => $this->id])->all();
}
public function getSiteImages(){
return InstallationImagesSite::find()->where(['installation_id' => $this->id])->all();
}
public function getUser(){
return User::find()->where(['id'=>$this->created_by]);
}
public function getTeamsuser()
{
return $this->hasMany(User::className(), ['id' => 'created_by']);
}
}
Installation Search Model
class InstallationsSearch extends Installations
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'created_by', 'updated_by', 'status'], 'integer'],
[['ref_no','meter_type','install_type', 'meter_msn', 'billing_msn',
'tarrif', 'created_at','created_by', 'updated_at', 'latitude',
'longitude', 'site_issues', 'istallation_status', 'comm_status',
'customer_id', 'consumer_name', 'consumer_address', 's_load',
'so_person_name', 'so_phone_number', 'so_person_designation','imsi_no',
'meter_id' , 'Meter_Serial_Number' ,'Meter_Type','Sub_Division_Code','Sub_Division_Name'], '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 = Installations::find();
// 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,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'created_by' => $this->created_by,
'updated_by' => $this->updated_by,
'meter_type' => $this->meter_type,
'install_type'=>$this->install_type,
'istallation_status'=>$this->istallation_status,
'status' => $this->status,
]);
$query->andFilterWhere(['like', 'ref_no', $this->ref_no])
->andFilterWhere(['like', 'meter_msn', $this->meter_msn])
->andFilterWhere(['like', 'billing_msn', $this->billing_msn])
->andFilterWhere(['like', 'tarrif', $this->tarrif])
->andFilterWhere(['like', 'latitude', $this->latitude])
->andFilterWhere(['like', 'longitude', $this->longitude])
->andFilterWhere(['like', 'site_issues', $this->site_issues])
->andFilterWhere(['like', 'istallation_status', $this->istallation_status])
->andFilterWhere(['like', 'comm_status', $this->comm_status])
->andFilterWhere(['like', 'customer_id', $this->customer_id])
->andFilterWhere(['like', 'consumer_name', $this->consumer_name])
->andFilterWhere(['like', 'consumer_address', $this->consumer_address])
->andFilterWhere(['like', 's_load', $this->s_load])
->andFilterWhere(['like', 'so_person_name', $this->so_person_name])
->andFilterWhere(['like', 'so_phone_number', $this->so_phone_number])
->andFilterWhere(['like','meter_type',$this->meter_type])
->andFilterWhere(['like','created_by',$this->created_by])
//->andFilterWhere(['like', 'imsi_no', $this->imsi_no])
->andFilterWhere(['like', 'so_person_designation', $this->so_person_designation]);
if (!Yii::$app->user->isGuest && in_array(Yii::$app->user->identity->user_role, [3,4])) {
$query->joinWith('teamsuser', true);
$query->andFilterWhere(['=', 'user.group_id', Yii::$app->user->identity->group_id]);
}
$query->orderBy(['id' => SORT_DESC]);
return $dataProvider;
}
}
How can I add these two options in the grid view?
Any help would be highly appreciated.
Update 2
As per answer given I have updated my code
InstallationsSearch
class InstallationsSearch extends Installations
{
public $meter_id;
public $Meter_Serial_Number;
public $Meter_Type;
public $Sub_Division_Code;
public $Sub_Division_Name;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'created_by', 'updated_by', 'status'], 'integer'],
[['ref_no','meter_type','install_type', 'meter_msn', 'billing_msn', 'tarrif', 'created_at','created_by', 'updated_at', 'latitude', 'longitude', 'site_issues', 'istallation_status', 'comm_status', 'customer_id', 'consumer_name', 'consumer_address', 's_load', 'so_person_name', 'so_phone_number', 'so_person_designation','imsi_no','meter_id' , 'Meter_Serial_Number' ,'Meter_Type','Sub_Division_Code','Sub_Division_Name'], '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 = Installations::find();
// 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,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'created_by' => $this->created_by,
'updated_by' => $this->updated_by,
'meter_type' => $this->meter_type,
'install_type'=>$this->install_type,
'istallation_status'=>$this->istallation_status,
'status' => $this->status,
]);
$query->andFilterWhere(['like', 'ref_no', $this->ref_no])
->andFilterWhere(['like', 'meter_msn', $this->meter_msn])
->andFilterWhere(['like', 'billing_msn', $this->billing_msn])
->andFilterWhere(['like', 'tarrif', $this->tarrif])
->andFilterWhere(['like', 'latitude', $this->latitude])
->andFilterWhere(['like', 'longitude', $this->longitude])
->andFilterWhere(['like', 'site_issues', $this->site_issues])
->andFilterWhere(['like', 'istallation_status', $this->istallation_status])
->andFilterWhere(['like', 'comm_status', $this->comm_status])
->andFilterWhere(['like', 'customer_id', $this->customer_id])
->andFilterWhere(['like', 'consumer_name', $this->consumer_name])
->andFilterWhere(['like', 'consumer_address', $this->consumer_address])
->andFilterWhere(['like', 's_load', $this->s_load])
->andFilterWhere(['like', 'so_person_name', $this->so_person_name])
->andFilterWhere(['like', 'so_phone_number', $this->so_phone_number])
->andFilterWhere(['like','meter_type',$this->meter_type])
->andFilterWhere(['like','created_by',$this->created_by])
//->andFilterWhere(['like', 'imsi_no', $this->imsi_no])
->andFilterWhere(['like', 'so_person_designation', $this->so_person_designation]);
if (!Yii::$app->user->isGuest && in_array(Yii::$app->user->identity->user_role, [3,4])) {
$query->joinWith('teamsuser', true);
$query->andFilterWhere(['=', 'user.group_id', Yii::$app->user->identity->group_id]);
}
$query->orderBy(['id' => SORT_DESC]);
return $dataProvider;
}
/**
* #param $params
* #return SqlDataProvider
* #throws \yii\db\Exception
*/
public function searchInstallations($params )
{
$query = /** #lang text */
"SELECT DISTINCT
m.`id` AS meter_id,
ins.`meter_msn` AS Meter_Serial_Number,
ins.`meter_type` AS Meter_Type,
sd.`sub_div_code` AS Sub_Division_Code,
sd.`name` AS Sub_Division_Name
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` =
map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` =
sd.`sub_div_code`
WHERE ins.`meter_type` = :meter_type
AND sd.`sub_div_code` = :sub_div
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM
`meter_acceptance_details` md WHERE md.`flag` IN (1))";
$queryParams = [
':meter_type' => $params['meter_type'] ,
':sub_div' => $params['sub_div']
];
$queryCount = /** #lang text */
"SELECT COUNT(DISTINCT m.`id`)
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` = map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` = sd.`sub_div_code`
WHERE ins.`meter_type` = :meter_type
AND sd.`sub_div_code` = :sub_div
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM
`meter_acceptance_details` md WHERE md.`flag` IN (1))";
$dataProvider = new SqlDataProvider ( [
'sql' => $query ,
'pagination' => [
'pageSize' => 60 ,
] ,
] );
if ( !($this->load ( $params ) && $this->validate ()) ) {
return $dataProvider;
}
if($this->Meter_Serial_Number!==''){
$dataProvider->sql .= ' AND ins.meter_msn like :meter_serial_number';
$queryParams[':meter_serial_number'] = $this->Meter_Serial_Number . '%';
$queryCount .= ' AND ins.meter_msn like :meter_serial_number';
}
if($this->Sub_Division_Code!==''){
$dataProvider->sql .= ' AND sd.sub_div_code like :sub_div_code';
$queryParams[':sub_div_code'] = $this->Sub_Division_Code . '%';
$queryCount .= ' AND sd.sub_div_code like :sub_div_code';
}
$count = Yii::$app->db->createCommand ( $queryCount , $queryParams )->queryScalar ();
$dataProvider->totalCount = $count;
$dataProvider->params = $queryParams;
//add to session
$session = Yii::$app->session;
$session->set ( 'my_sql' , Yii::$app->db->createCommand ( $query , $queryParams )->rawSql );
$session->set ( 'total' , $count );
//return data provider
return $dataProvider;
}
}
Controler Code
public function actionViewcreated( $id ) {// passed the id of my model which is created in the previous step
$model = $this->findModel ( $id ); // this will find my model/record based on the id
$sub_div = $model->sub_div;
$meter_type = $model->meter_type;
$queryParams = Yii::$app->request->queryParams;
$queryParams['sub_div'] = $sub_div;
$queryParams['meter_type'] = $meter_type;
$searchModel = new InstallationsSearch();
$dataProvider = $searchModel->searchInstallations( $queryParams );
if ( Yii::$app->session->get ( 'total' ) <= 0 ) {
$this->findModel ( $id )->delete ();
\Yii::$app->getSession ()->setFlash ( 'errors' , '
<div class="alert alert-error alert-dismissable">
<button aria-hidden="true" data-dismiss="alert" class="close"
type="button">×</button>
<strong>There are no meters installed against the selected Sub Division!!!! </strong>Acceptance is not Created</div>' );
return $this->redirect ( [ 'index' , 'id' => $model->id ] );
}
return $this->render ( 'viewcreated' , [
'dataProvider' => $dataProvider ,
'model' => $model ,
'id' => $model->id ,
'searchModel' => $searchModel
] );
}
View
<?= GridView::widget([
'dataProvider' => $dataProvider,
//'ajaxUpdate' => true,
//'filterModel' => $searchModel,
'id'=>'gv',
'columns' => [
['class' => 'yii\grid\SerialColumn'],
['class' => 'yii\grid\CheckboxColumn', 'checkboxOptions' => function($d) {
return ['value' => $d['meter_id']];
}],
[
'attribute'=>'Meter_Serial_Number',
'filter'=> \yii\helpers\Html::activeTextInput($searchModel, 'Meter_Serial_Number',['class'=>'form-control']),
],
'Meter_Type',
'Sub_Division_Code',
[
'attribute' => 'Sub_Division_Name',
'filter'=> \yii\helpers\Html::activeTextInput($searchModel,'Sub_Division_Name', ['class'=>'form-control']),
],
],
]); ?>
Update 3
After updating my code I got search filters on both the Meter Serial and Sub Division
But when I try to search a serial number then the page got refreshed and again I see the full view
By echo $dataProvider->sql; I got
SELECT DISTINCT m.idAS meter_id, ins.meter_msnAS Meter_Serial_Number, ins.meter_typeAS Meter_Type, sd.sub_div_codeAS Sub_Division_Code, sd.nameAS Sub_Division_Name FROMinstallationsins INNER JOINmetersm ON ins.meter_msn= m.meter_msnINNER JOINmeter_acceptance_headermap ON ins.meter_type= map.meter_typeINNER JOINsurveysur ON ins.ref_no= sur.ref_noINNER JOINsurvey_hesco_subdivisionsd ON sur.sub_division= sd.sub_div_codeWHERE ins.meter_type= :meter_type AND sd.sub_div_code= :sub_div AND map.idNOT IN (SELECT DISTINCT md.meter_idFROMmeter_acceptance_detailsmd WHERE md.flagIN (1)) AND ins.meter_msn like :meter_serial_number AND sd.sub_div_code like :sub_div_code
The above query remains the same whether I have searched for any serial number or not.
Note: I already know how to add a search option by adding a filter field in a calculated column in my search model. But as I have a custom view so I am confused that how can I do it.
I have'nt used it quite though with the GridView and there could be better solutions than this one if anyone could suggest but this can work the way you want.
You should update your InstallationSearch model to use the filter with the GridView.If you are not using the default InstallationSearch model's search() function anywhere then you can update the existing search method or else create a separate method. I assume you are not using it anywhere else and I will add a search function that will use the SqlDataProvider for displaying and filtering the GridView.
To implement the search you need to identify how many aliases are you using for the columns you have to declare all of them as public attributes of your search model
public $meter_id;
public $Meter_Serial_Number;
public $Meter_Type;
public $Sub_Division_Code;
public $Sub_Division_Name;
then add them to the safe rule
public function rules() {
return [
[ [ 'meter_id' , 'Meter_Serial_Number' ,'Meter_Type','Sub_Division_Code','Sub_Division_Name'] , 'safe' ] ,
];
}
Now add the search() function
public function searchInstallations($params)
{
$query = "SELECT DISTINCT
m.`id` AS meter_id,
ins.`meter_msn` AS Meter_Serial_Number,
ins.`meter_type` AS Meter_Type,
sd.`sub_div_code` AS Sub_Division_Code,
sd.`name` AS Sub_Division_Name
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` = map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` = sd.`sub_div_code`
WHERE ins.`meter_type` = :meter_type
AND sd.`sub_div_code` = :sub_div
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM
`meter_acceptance_details` md WHERE md.`flag` IN (1))";
$queryParams = [
':meter_type' => $params['meter_type'],
':sub_div' => $params['sub_div']
];
$queryCount = "SELECT COUNT(DISTINCT m.`id`)
FROM `installations` ins
INNER JOIN `meters` m ON ins.`meter_msn` = m.`meter_msn`
INNER JOIN `meter_acceptance_header` map ON ins.`meter_type` = map.`meter_type`
INNER JOIN `survey` sur ON ins.`ref_no` = sur.`ref_no`
INNER JOIN `survey_hesco_subdivision` sd ON sur.`sub_division` = sd.`sub_div_code`
WHERE ins.`meter_type` = :meter_type
AND sd.`sub_div_code` = :sub_div
AND map.`id` NOT IN (SELECT DISTINCT md.`meter_id` FROM `meter_acceptance_details` md WHERE md.`flag` IN (1))";
$dataProvider = new SqlDataProvider(
[
'sql' => $query,
'pagination' => [
'pageSize' => 40
]
]
);
if (!($this->load($params) && $this->validate())) {
$dataProvider->params = $queryParams;
$count = Yii::$app->db->createCommand($queryCount, $queryParams)->queryScalar();
$dataProvider->totalCount = $count;
return $dataProvider;
}
if ($this->Meter_Serial_Number !== '') {
$dataProvider->sql .= ' AND ins.meter_msn like :meter_serial_number';
$queryParams[':meter_serial_number'] = $this->Meter_Serial_Number . '%';
$queryCount .= ' AND ins.meter_msn like :meter_serial_number';
}
if ($this->Sub_Division_Code !== '') {
$dataProvider->sql .= ' AND sd.sub_div_code like :sub_div_code';
$queryParams[':sub_div_code'] = $this->Sub_Division_Code . '%';
$queryCount .= ' AND sd.sub_div_code like :sub_div_code';
}
$count = Yii::$app->db->createCommand($queryCount, $queryParams)->queryScalar();
$dataProvider->totalCount = $count;
$dataProvider->params = $queryParams;
//add to session
$session = Yii::$app->session;
$session->set('my_sql', Yii::$app->db->createCommand($query, $queryParams)->rawSql);
$session->set('total', $count);
//return data provider
return $dataProvider;
}
Update your actionViewcreated to the following
public function actionViewcreated($id)
{
// passed the id of my model which is created in the previous step
$model = $this->findModel($id); // this will find my model/record based on the id
$sub_div = $model->sub_div;
$meter_type = $model->meter_type;
$queryParams = Yii::$app->request->queryParams;
$queryParams['sub_div'] = $sub_div;
$queryParams['meter_type'] = $meter_type;
$searchModel = new InstallationSearch();
$dataProvider = $searchModel->searchInstallation($queryParams);
if (Yii::$app->session->get('total') <= 0) {
$this->findModel($id)->delete();
\Yii::$app->getSession()->setFlash(
'errors',
'<div class="alert alert-error alert-dismissable"><button aria-hidden="true" data-dismiss="alert" class="close" type="button">×</button>
<strong>There are no meters installed against the selected Sub Division!!!! </strong>Acceptance is not Created</div>'
);
return $this->redirect(['index', 'id' => $model->id]);
}
return $this->render(
'viewcreated', [
'dataProvider' => $dataProvider,
'model' => $model,
'id' => $model->id,
'searchModel' => $searchModel
]
);
}
and enable the filter for the grid view like below
[
'attribute'=>'Meter_Serial_Number',
'filter'=> \yii\helpers\Html::activeTextInput($searchModel, 'Meter_Serial_Number',['class'=>'form-control']),
],
[
'attribute' => 'Sub_Division_Name',
'filter'=> \yii\helpers\Html::activeTextInput($searchModel,'Sub_Division_Name', ['class'=>'form-control']),
],
EDIT
For making your dropdown work either change the function toArrayList() to the following if it is not used anywhere else or create a separate function as you need to have the sub_div_name as the value to be searched in the table so change the sub_div_code to the field which has the sub_div_name i assume it is the name field in the SurveyHescoSubdivision .
/**
* #return mixed
*/
public static function toArrayList()
{
return ArrayHelper::map(
self::find()->all(), 'name', function ($model, $defaultValue) {
return $model['sub_div_code'] . ' - ' . $model['name'];
}
);
}

Yii search method get don't work and don't compare with data in database

Hi yesterday i tried one way to create search by datetime, and you can see link: Search task on the next post.
Today I try one another way: When I succed i will put sollution back thank you.
This is my search file:
<?php Yii::app()->clientScript->registerCoreScript('jquery'); ?>
<?php
/* #var $this ApplicationController */
/* #var $model Application */
/* #var $form CActiveForm */
?>
<div class="wide form">
<?php $form=$this->beginWidget('CActiveForm', array(
'action'=>Yii::app()->createUrl($this->route),
'method'=>'get',
'enableAjaxValidation'=>false,
//$model->search(),
)); ?>
<div class="row">
<?php echo $form->label($model,'AUUsername'); ?>
<?php echo $form->textField($model,'AUUsername',array('size'=>45,'maxlength'=>45)); ?>
</div>
<div class="row">
<?php
//datepicker for date_from
echo CHtml::label("From date", 'datepicker');
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'name' => 'filters[date_from]',
//'value' => $filters['date_from'],
// additional javascript options for the date picker plugin
'options' => array(
'showButtonPanel' => true,
'showAnim' => 'slide', //'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop'
'dateFormat'=>'yyyy-mm-dd hh:mm:ss',
),
'htmlOptions' => array(
'id'=>'date_from',
),
));?>
</div>
<div class="row">
<?php
//datepicker for date to
echo CHtml::label("To date", 'datepicker');
$this->widget('zii.widgets.jui.CJuiDatePicker', array(
'name' => 'filters[date_to]',
//'value' => $filters['date_to'],
// additional javascript options for the date picker plugin
'options' => array(
'showButtonPanel' => true,
'showAnim' => 'slide', //'slide','fold','slideDown','fadeIn','blind','bounce','clip','drop'
'dateFormat'=>'yyyy-mm-dd hh:mm:ss',
),
'htmlOptions' => array(
'id'=>'date_to',
),
));?>
</div>
<div class="row buttons">
<?php echo CHtml::submitButton('Search'); ?>
</div>
<?php $this->endWidget(); ?>
</div>
This is my model file:
<?php
class AppLog extends AltActiveRecord
{
private $_ActionName=null;
public $date_from;
public $date_to;
public function getDbConnection(){
return Yii::app()->connectionManager->getConnection(Yii::app()->user->getState('application'));
}
public function relations ()
{
return array (
'actions'=>array(self::HAS_ONE, 'Actions', array('ActionID'=>'ActionID')),
);
}
public function getActionName()
{
if ($this->_ActionName === null && $this->actions !== null)
{
$this->_ActionName = $this->actions->ActionName;
}
return $this->_ActionName;
}
public function setActionName($value)
{
$this->_ActionName = $value;
}
public function tableName()
{
return 'applog';
}
public function rules()
{
return array(
array('AppUserID','length', 'max'=>11),
array('AUUsername','length', 'max'=>45),
array('AUActionTime','type','type'=>'datetime','datetimeFormat'=>'yyyy-mm-dd hh:mm:ss'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('AppUserID,AUUsername, date_from, date_to', 'safe', 'on'=>'search'),
);
}
public function attributeLabels()
{
return array(
'ActionID' => 'ID',
'AUUsername' => 'Naziv korisnika',
'AUActionTime' => 'Vrijeme akcije',
);
}
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('APUsername',$this->AUUsername,true);
$criteria->compare('AUActionTime',$this->AUActionTime,true);
$criteria->compare('date_from',$this->date_from,true);
$criteria->compare('date_to',$this->date_to,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
?>
THIS IS MY CONTROLLER ACTION FOR SEARCH
public function actionLista()
{
$model = new Datalist;
$this->layout='column1';
//
if($_GET!=null)
{
$date_from = $_GET['filters']['date_from'];
$params[':date_from'] = date('yyyy-mm-dd hh:mm:ss', strtotime($_GET['filters']['date_from']));
$date_to = $_GET['filters']['date_to'];
$params[':date_to'] = date('yyyy-mm-dd hh:mm:ss', strtotime($_GET['filters']['date_to']));
if($date_from == '') $params[':date_from'] = date('yyyy-mm-dd hh:mm:ss', strtotime('2014-01-01 00:00:00'));
if($date_to == '') $params[':date_to'] = date('yyyy-mm-dd hh:mm:ss', strtotime('2999-01-01 00:00:00'));
//$condition = '(AUActionTime>:date_from OR AUActionTime<:date_to)';
//set filters
//$this->setFilters($_GET['filters']);
//die(CVarDumper::dump($params,10,true));
}
else {
$this->filters = array(
'date_from' => date('yyyy-mm-dd hh:mm:ss', strtotime('2014-01-01')),
'date_to' => date('yyyy-mm-dd hh:mm:ss', strtotime('today + 1 day')),
);
}
1) In your controller you should set the scenario as "search" like this
$model = new Datalist('search');
$model->unSetAttributes();
2) You need to assign the $_GET values to the model before view is rendered like this
// If your get vars are different then accordingly
if(isset($_GET['AppLog'])){
$model->attributes = $_GET['AppLog'];
....
$model->date_to = $date_to // After you retrieved and formatted from $_GET as above
$model->date_from = $date_from
Your controller action does not seem to rendering a view; i am assuming that you have omitted it here, but you are displaying the output in someway

zend : Fatal error: Class 'Application_Model_User' not found

I am trying connecting to my model class defined in /application/models named user.php.
Following is how my Bootstrap looks like:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap{
protected function _initAppAutoload() {
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH,
'resourceTypes' => array(
'model' => array(
'path' => 'models',
'namespace' => 'Model',
)
)
));
echo '<pre>';
var_dump($autoloader);
return $autoloader;
}
}
Folling is my application.ini
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
Following is my IndexController.php
class IndexController extends Zend_Controller_Action {
private $user_connection;
private $login_status;
public function init() {
/* Initialize action controller here */
$this->user_connection = new Application_Model_User();
}
public function indexAction() {
$sql = " SELECT *
FROM USER";
$this->view->deals = $this->user_connection->select($sql);
}
following is my user.php file:
class Application_Model_User extends Application_Model_Db_Connection {
public function __construct() {
parent::__construct();
}
public function Connection(){
return $this->getConnection();
}
public function insert($data, $table = 'user'){
return parent::insert($table, $data);
}
public function select($sql){
return parent::select($sql);
}
}
Strange part is, I am developing on windows and everything runs fine, but when I push the same code to my ec2 linux instance, I get this fatal error.
Fatal error: Class 'Application_Model_User' not found in /var/www/html/dev/application/controllers/IndexController.php on line 11
I went through many questions on stack overflow and tried most of them, but I am not close to solve this problem. Any help would be appreciated.
I was able to fix the above issue, it was due to case sensitivity of linux. I renamed my models with first letter capital and was able to access them in my Controller.
user.php -> User.php
also for adding subfolder to your model you can add following to the bootstrap.
protected function _initAppAutoload() {
$autoloader = new Zend_Loader_Autoloader_Resource(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH,
'resourceTypes' => array(
'model' => array(
'path' => 'models/',
'namespace' => 'Model_',
),
'model_db' => array(
'path' => 'models/db',
'namespace' => 'Model_Db_'
)
)
));

drupal 7 custom content hook_theme output

I have a custom module created in Drupal 7 and I want it to display some HTML content. Here is how I have did.
But it is not working, what I do wrong?
<?php
/**
* Implements hook_block_info().
*/
function submenus_block_info() {
$blocks = array();
$blocks['info'] = array(
'info' => t('The submenu zone')
);
return $blocks;
}
/**
* Implements hook_block_view().
*
*/
function submenus_block_view($delta = '') {
$block = array();
$users = "edf";
$title = "sdfsd";
$block['subject'] = t('Submenu');
$block['content'] = theme('submenus_output', array('users' => $users, 'title' => $title));
return $block;
}
/**
* Implement hook_theme()
*/
function submenus_theme() {
return array(
'submenus_output' => array(
'variables' => array('users' => NULL, 'title' => NULL),
),
);
}
/**
* Display output
*/
function theme_submenus_output($somearray) {
$content = '<div>TEST</div>';
return $content;
}
?>
I checked, there is nothing wrong with that code: the new block is available in the list of blocks, and if you assign it to a region, the block is called and the code from the custom theme function is displayed.
So you could try these things:
in Administration > Configuration > Development > Performance, clear the caches
in Administration > Structure > Blocks, make sure the block is assigned to a region that exists (such as "Content") and if it is, click the "Configure" link to see if there is a filter that prevents it from being displayed.

Resources