I had a cgridview with an ajaxlink in one of the column. The ajaxlink works fine in the first page only. For other pages, no matter how i click the ajaxlink it will update the result in first page.
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'promotion-facility-grid',
'ajaxUpdate'=>true,
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array( 'name'=>'pf_branch', 'value'=>'$data->pfBranch->branch_name'),
array( 'name'=>'pf_category', 'value'=>'$data->pfCategory->pc_name'),
array( 'name'=>'pf_photo', 'type' => 'raw', 'value'=>'CHtml::image(Yii::app()->baseUrl . "/images/facility/" .$data->pf_photo, "", array("width"=>"150px"))'),
'pf_name',
array(
'name' => 'pf_main_view',
'htmlOptions'=>array('style'=>'text-align: center'),
'value' => 'CHtml::ajaxLink("<span id=\'MV$data->pf_id\'>$data->pf_main_view</span>", array("promotionFacility/Ajaxcontent", "id"=>$data["pf_id"]),array("update" => "#MV$data->pf_id"))',
'type' => 'raw',
),
/*
'pf_price',
'pf_currency',
'pf_link',
'pf_status',
*/
array(
'class'=>'CButtonColumn',
'template'=>'{update}{delete}',
'buttons'=>array
(
'update' => array
(
'label'=>'update',
'url'=>'Yii::app()->createUrl("promotionFacility/updatepanel", array("id"=>$data->pf_id,"view"=>$data->pf_view,"branch"=>$data->pf_branch))',
),
),
),
),
));
controller
public function actionAjaxcontent($id)
{
include("js/databaseconnection.php");
$query = "select * from holiday_promotion_facility where pf_id='$id'";
$result= mysql_query($query) or die (mysql_error());
while ($row=mysql_fetch_array($result))
{
$pf_main_view = $row['pf_main_view'];
}
if ($pf_main_view == "yes")
{
mysql_query("update holiday_promotion_facility set pf_main_view='no' where pf_id='$id'");
echo "no";
}
else
{
mysql_query("update holiday_promotion_facility set pf_main_view='yes' where pf_id='$id'");
echo "yes";
}
}
what do I miss out? is it anything to do with ajaxupdate or afterajaxupdate?
Yes you miss afterAjaxUpdate(). You loading grid, but does'nt update events.
I recommend to do:
array(
'name' => 'pf_main_view',
'htmlOptions'=>array('style'=>'text-align: center'),
'value' => function($data){
return CHtml::link("<span id='MV$data->pf_id'>$data->pf_main_view</span>","",array("onclick"=>"js:ajax_function(".$data->pf_id.")")),
},
'type' => 'raw',
),
In your js you'll have to do:
function ajax_function(id){
$.ajax({
//your request here
//id is your parameter from grid
});
}
In this case you don't need to do afterAjaxUpdate() and bind events by hands.
Related
I have simple Yii cgridview code with pagination. Pagination is working fine but in the last page I have faced one issue.
For example, If I have 13 records in DB table, and set pagination for 10 pages per page then for first page It will show "1 - 10 of 13 results" but when I clicked on 2nd page link then It will show "4 - 13 of 13" instead of "11 - 13 of 13".
Here is my code.
1) Controller :
function actiontransactionHistory(){
$creditTransactionObj = new CreditTransaction();
$this->render('history',array(
'creditTransactionObj'=>$creditTransactionObj,
));
}
2) Model :
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id,true);
$criteria->compare('fkasmtGroupId',$this->fkasmtGroupId);
$criteria->compare('fkgroupSurveyUserId',$this->fkgroupSurveyUserId,true);
$criteria->compare('fkasmtId',$this->fkasmtId);
$criteria->compare('transaction_type',$this->transaction_type);
$criteria->compare('credit_type',$this->credit_type,true);
$criteria->compare('credit_qty',$this->credit_qty);
$criteria->compare('transaction_date',$this->transaction_date,true);
$criteria->compare('isDelete',$this->isDelete);
$criteria->compare('status',$this->status);
$criteria->compare('created_at',$this->created_at,true);
$criteria->compare('modified_at',$this->modified_at,true);
$sort = array(
"defaultOrder" => "transaction_date DESC",
);
return new CActiveDataProvider($this, array(
"criteria"=>$criteria,
"sort" => $sort,
));
}
3) View:
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'id' => 'history-grid',
'dataProvider' => $creditTransactionObj->search(),
'loadingCssClass' => '',
'enableSorting' => true,
'itemsCssClass' => 'my-teams',
'summaryText' => "Displaying {start} - {end} of {count} results.",
"emptyText" => "There is no transaction history available.",
'columns' => array(
array('name' => 'transaction_date', 'header' => 'Date', 'type' => 'raw', 'value' => 'date("d-M-Y",strtotime($data->transaction_date))', 'htmlOptions' => array('class' => '')),
array('name' => 'credit_qty', 'header' => '# of Credits', 'sortable'=>false, 'type' => 'raw', 'value' => '($data->transaction_type == 1) ? - $data->credit_qty : $data->credit_qty', 'htmlOptions' => array('class' => '')),
array('name' => 'credit_type', 'header' => 'Type', 'type' => 'raw', 'value' => '$data->credit_type', 'htmlOptions' => array('class' => '')),
array('name' => 'transaction_type', 'header' => 'Activity', 'type' => 'raw', 'value' => '($data->transaction_type == 0) ? "Purchased" : (($data->transaction_type == 1) ? "Spent" : "Refunded")', 'htmlOptions' => array('class' => '')),
array('name' => 'fkasmtGroupId', 'header' => 'Group Name', 'type' => 'raw', 'value' => array($this,'getGroupName'), 'htmlOptions' => array('width' => '35%')),
)
));
?>
I have also attached both pages screenshot.
Any help will be appreciate. Thanks in advance !
After spending lots of hours finally I found the solution for this issue.
Actually the problem was in fetchData() function which is used in
yii/framework/web/CActiveDataProvider.php framework class file.
In fetchData() method, limit was not calculated properly for the last page pagination. so I have made changes to calculate correct limit.
Old Code:
protected function fetchData()
{
$criteria=clone $this->getCriteria();
if(($pagination=$this->getPagination())!==false)
{
$pagination->setItemCount($this->getTotalItemCount());
$pagination->applyLimit($criteria);
}
$baseCriteria=$this->model->getDbCriteria(false);
if(($sort=$this->getSort())!==false)
{
// set model criteria so that CSort can use its table alias setting
if($baseCriteria!==null)
{
$c=clone $baseCriteria;
$c->mergeWith($criteria);
$this->model->setDbCriteria($c);
}
else
$this->model->setDbCriteria($criteria);
$sort->applyOrder($criteria);
}
$this->model->setDbCriteria($baseCriteria!==null ? clone $baseCriteria : null);
$data=$this->model->findAll($criteria);
$this->model->setDbCriteria($baseCriteria); // restore original criteria
return $data;
}
New Code:
protected function fetchData()
{
$criteria=clone $this->getCriteria();
if(($pagination=$this->getPagination())!==false)
{
$pagination->setItemCount($this->getTotalItemCount());
$pagination->applyLimit($criteria);
// update limit to the correct value for the last page
$limit=$pagination->getLimit();
$offset=$pagination->getOffset();
if ( $offset+$limit > $pagination->getItemCount() )
$criteria->limit = $pagination->getItemCount() - $offset;
}
$baseCriteria=$this->model->getDbCriteria(false);
if(($sort=$this->getSort())!==false)
{
// set model criteria so that CSort can use its table alias setting
if($baseCriteria!==null)
{
$c=clone $baseCriteria;
$c->mergeWith($criteria);
$this->model->setDbCriteria($c);
}
else
$this->model->setDbCriteria($criteria);
$sort->applyOrder($criteria);
}
$this->model->setDbCriteria($baseCriteria!==null ? clone $baseCriteria : null);
$data=$this->model->findAll($criteria);
$this->model->setDbCriteria($baseCriteria); // restore original criteria
return $data;
}
But remember, never update a core class file of framework. so I just extend this method in my Model file and write below code.
Final Code In My Model file without change in framework file:
class CustomActiveDataProvider extends CActiveDataProvider
{
/**
* Fetches the data from the persistent data storage.
* #return array list of data items
*/
protected function fetchData()
{
$criteria=clone $this->getCriteria();
if(($pagination=$this->getPagination())!==false)
{
$pagination->setItemCount($this->getTotalItemCount());
$pagination->applyLimit($criteria);
// update limit to the correct value for the last page
$limit=$pagination->getLimit();
$offset=$pagination->getOffset();
if ( $offset+$limit > $pagination->getItemCount() )
$criteria->limit = $pagination->getItemCount() - $offset;
}
$baseCriteria=$this->model->getDbCriteria(false);
if(($sort=$this->getSort())!==false)
{
// set model criteria so that CSort can use its table alias setting
if($baseCriteria!==null)
{
$c=clone $baseCriteria;
$c->mergeWith($criteria);
$this->model->setDbCriteria($c);
}
else
$this->model->setDbCriteria($criteria);
$sort->applyOrder($criteria);
}
$this->model->setDbCriteria($baseCriteria!==null ? clone $baseCriteria : null);
$data=$this->model->findAll($criteria);
$this->model->setDbCriteria($baseCriteria); // restore original criteria
return $data;
}
}
// Used this custome active data provider as shown in below.
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id,true);
$criteria->compare('isDelete',$this->isDelete);
$criteria->compare('status',$this->status);
$criteria->compare('created_at',$this->created_at,true);
$criteria->compare('modified_at',$this->modified_at,true);
$sort = array(
"defaultOrder" => "transaction_date DESC",
);
return new CustomActiveDataProvider($this, array(
"criteria"=>$criteria,
"sort" => $sort,
"pagination" => array('pageSize' => (isset($_REQUEST['pageSize'])?$_REQUEST['pageSize']:10))
));
}
After this change, Last page pagination works completely fine.
Thanks!
I need some data added default in the editor.
Like I want a template to get loaded in editor when I click on edit template option..
Can anyone suggest me some tip??
Here you can see how it can be done
$dataa= $this->getTemplate1();
$fieldset->addField('content', 'editor', array(
'name' => 'content',
'label' => Mage::helper('abandonedcart')->__('Content'),
'title' => Mage::helper('abandonedcart')->__('Content'),
'style' => 'width:700px; height:500px;',
'wysiwyg' => true,
'required' => true,
'state' => 'html',
'config' => $wysiwygConfig,
'value'=> $dataa,
));
if (Mage::getSingleton('adminhtml/session')->getAbandonedcartData()) {
$form->addValues(Mage::getSingleton('adminhtml/session')->getAbandonedcartData());
Mage::getSingleton('adminhtml/session')->setAbandonedcartData(null);
} elseif (Mage::registry('abandonedcart_data')) {
$form->addValues(Mage::registry('abandonedcart_data')->getData());
}
return parent::_prepareForm();
}
and calling a function to have data
public function getTemplate1() {
$emailTemplate = Mage::getModel('core/email_template')->loadDefault('abandonedcart_abandonedcart_group_email_template');
$emailTemplate['template_text'];;
$template_id = Mage::getStoreConfig('abandonedcart/abandonedcart_group/email_template');
$emailTemplate = Mage::getModel('core/email_template')->loadDefault($template_id);
return $processedTemplate = $emailTemplate->getProcessedTemplate();
}
With YII, I'm trying to make a query from a page called from ajax
echo CHtml::ajaxLink(
'Test request',
array('ajax/z1_gerar_excel.php',
'type'=>'POST',
'data' => array('sql' => $sql)
),
array('update'=>'#req_res'
)
);
?>
<div id="req_res">...</div>
and here is the AJAX page:
$sql = $_REQUEST['data']['sql'];
//echo $sql;
$connection=Yii::app()->db;
$command = $connection->createCommand($sql);
$dataReader = $command->query();
$cont_l = 1;
while(($row = $dataReader->read()) !== false)
{
echo "<br>Linha $cont_l: ";
print_r($row);
$cont_l++;
}// WHILE EOF
$connection->active = false;
and I have the following problem, the YII class is not initialized in the page called from ajax, so I get the following result:
Fatal error: Class 'Yii' not found in D:\Programas\Xampp\Instalado2\htdocs\atayo-teste\ajax\z1_gerar_excel.php on line 4
I've only been using YII for one week. How can I resolve this error?
UPDATE:
So i tried change it to a more YII way, i followed the example from http://lostmahbles.com/simple-yii-ajaxlink/ and add this to my view(z1_sql.php):
echo CHtml::ajaxLink(
"Link Text",
Yii::app()->createUrl( 'application/controllers/RelatorioController/ajaxRequest' ),
array( // ajaxOptions
'type' => 'POST',
'beforeSend' => "function( request )
{
// Set up any pre-sending stuff like initializing progress indicators
}",
'success' => "function( data )
{
// handle return data
alert( data );
}",
'data' => array( 'val1' => '1', 'val2' => '2' )
),
array( //htmlOptions
'href' => Yii::app()->createUrl( 'application/controllers/RelatorioController/ajaxRequest' ),
'class' => 'actionAjaxRequest'
)
);
and this to my controller(RelatorioController.php):
public function accessRules()
{
return array(
array('allow',
'actions'=>array('ajaxrequest'),
'users'=>array('#'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
public function actionAjaxRequest()
{
$val1 = $_POST['val1'];
$val2 = $_POST['val2'];
echo "some sort of response";
Yii::app()->end();
}
but i`m getting a 404 ERROR. And again, really noobie into YII, so anything at all helps...
You're not requesting a Yii php function/page.
Change your code to something like this: (not tested)
<?php
echo ajaxLink('text', array('ajax/z1_gerar_excel'), array(
'type' =>'POST',
'data' => array('sql' => $sql),
), array(
'update'=>'#req_res' // this array is for htmlOptions, so I think you want this parameter in the array with the ajax options
));
?>
Make sure you have an ajax controller with a function z1_gerar_excel.
For more information about the parameters of ajaxLink take a look at:
http://www.yiiframework.com/doc/api/1.1/CHtml#ajaxLink-detail
I have this search using joins. The results are correct but yii grid does not show all of the results even if the pagesize selected is greater than number of result.
here's my code :
if($_GET['BaseIar']['description'] !='empty'){
$criteria->with = array('class','classSi',);
$this->description=$_GET['BaseIar']['description'];
$criteria->compare('class.description', $this->description, true);
$criteria->compare('classSi.description', $this->description, true, 'OR');
}
here are the relations:
public function relations() {
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'class' => array(self::HAS_ONE, 'BaseEiEquipItem', 'iar_no'),
'classSi' => array(self::HAS_ONE, 'BaseSiReceivedItem','iar_no'),
);
}
here's the grid:
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'base-iar-grid',
'dataProvider'=>$searchModel->search(),
'columns'=>array(
array(
'class'=>'CCheckBoxColumn',
'id'=>'base-iar-id',
'selectableRows'=>2, // multiple rows can be selected
),
'iar_id',
'dateInspected',
array(
'name'=>'inspectedBy',
'value'=>'(!empty($data->inspectedBy))?$data->inspectedBy0->person->lastName.", ".$data->inspectedBy0->person->firstName." ".$data->inspectedBy0->person->middleName:"---"',
),
array(
'name'=>'endUser',
'value'=>'(!empty($data->endUser))?$data->endUser0->person->lastName.", ".$data->endUser0->person->firstName." ".$data->endUser0->person->middleName:"---"',
),
'dateReceived',
array(
'name'=>'receivedBy',
'value'=>'(!empty($data->receivedBy))?$data->receivedBy0->person->lastName.", ".$data->receivedBy0->person->firstName." ".$data->receivedBy0->person->middleName:"---"',
),
array(
'name'=>'requisitionOffice',
'value'=>'(!empty($data->requisitionOffice))?$data->requisitionOffice0->code:"---"',
'value'=>'$data->requisitionOffice0->code'
),
'prNo',
'poNo',
array(
'class'=>'InfosysButtonColumn',
'template'=>'{view}',
'afterDelete'=>'function(link,success,data){
if(success){
jSuccess("Delete completed successfully!");
}
}',
'buttons'=>array(
'view' => array(
'label' => 'View details',
'url' => 'Yii::app()->createUrl("pims/IAR/BaseIar/view", array("id"=>$data["id"]))'
),
),
'header'=>CHtml::activeDropDownList($model,'pageSize',array('10'=>'10','20'=>'20','30'=>'30','50'=>'50','100'=>'100','ALL'=>'All'),array('onchange'=>'$.fn.yiiGridView.update("base-iar-grid", {data:{pageSize:$(this).val()}});')),
),
)
));
What might be the correct way to declare multiple relations in $criteria->with?
Hey I found this piece of example code in the docs for with(), maybe it'll help you:
Post::model()->with(array(
'author'=>array('select'=>'id, name'),
'comments'=>array('condition'=>'approved=1', 'order'=>'create_time'),
))->findAll();
First, actually I'm not using CGridView, but I'm using TbExtendedGridView from YiiBooster. I use CGridView on the title because it's more familiar, but still these two things works in quite the same way.
I'm enabling inline edit on my TbExtendedGridView (TbJEditableColumn). TbExtendedGridView is using jquery's Jeditable for this functionality. This Jeditable also applicable to CGridView.
Thanks to this SO's question: Change the Row Color Based on the Column value in CGridView
I know how to change the row color. But, it's still not working with the inline edit functionality. So, my question is, how can that rowCssClassExpression be updated everytime I edit some value on a column?
This is my view's code on [root]/protected/views/transaction/admin.php
<?
$this->widget('bootstrap.widgets.TbExtendedGridView', array(
'id'=>'transaction-grid',
'rowCssClassExpression'=>'$data->getCssClass()',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'date',
'value'=> 'date("j M Y", strtotime($data->date))',
'htmlOptions' => array('style'=>'width:52px')
),
array(
'name' => 'amount',
'value' => 'number_format($data->amount, 0, ",", ".")',
'htmlOptions' => array('class'=>'currency', 'style'=>'width:72px')
),
array(
'name' => 'category_name',
'value'=>'$data->category->name',
'header'=>'Category',
'sortable' => 'true',
'htmlOptions' => array('style'=>'width:131px'),
'class'=>'bootstrap.widgets.TbJEditableColumn',
'jEditableOptions' => array(
'type' => 'optgroup',
'loadurl' => Yii::app()->baseUrl . '/index.php/transaction/getCategory',
'submitdata' => array('attribute'=>'category'),
'cssclass' => 'form',
'width' => '180px',
'submit' => 'save changes'
)
),
array(
'name'=>'desc',
'value'=>'$data->desc',
'htmlOptions' => array('class'=>'desccell'),
'class'=>'bootstrap.widgets.TbJEditableColumn',
'jEditableOptions' => array(
'type' => 'text',
// very important to get the attribute to update on the server!
'submitdata' => array('attribute'=>'desc'),
'cssclass' => 'form',
'width' => '180px',
)
),
array(
'htmlOptions' => array('nowrap'=>'nowrap'),
'class'=>'bootstrap.widgets.TbButtonColumn',
)
)
)
And this is my getCssClass code on [root]/protected/models/Transaction.php:
public function getCssClass(){
$categoryType = Category::model()->findByPk($this->categoryId)->getAttribute("type");
$categoryName = Category::model()->findByPk($this->categoryId)->getAttribute("name");
$class = "";
if($categoryName == "Uncategorized Income"){
$class = "darkgreen";
}
else if($categoryName == "Uncategorized Expense"){
return "darkred";
}
else if($categoryType == "INCOME"){
return "green ";
}
else if($categoryType == "EXPENSE" || $categoryType == "COST OF GOODS"){
return "red ";
}
else if($categoryType == "WITHDRAW" || $categoryType == "DEPOSIT" ){
return "blue ";
}
else{
return "grey ";
}
return $class . " " . $categoryName . " " . $categoryType;
}
Use the 'afterAjaxUpdate' attribute to fire a javascript function on any update.
'afterAjaxUpdate' => ' function(){ //enterJScode }',