Extension a basic set of columns of Yii grid. Allows you to organize interactive editing data inside the grid. The new values will be sent to the server using Ajax. At the moment includes:
- phaSelectColumn - column, which will allow the new data from a predefined list of values.
- phaCheckColumn - using this column you will be switched the state between two value.
Requirements ¶
Testing with Yii 1.1.7, but should work since Yii 1.1.
Licence ¶
Choose your favourite of - GPL or MIT.
Installation ¶
- Extract the release file under protected/extensions/phaActiveColumn.
- Add to your config file in import section:
... 'application.extensions.phaActiveColumn.*', ...
Usage ¶
Now in your template you can use the new column. All new collumns must set property actionUrl. It's URL for update action.On this URL will be sent call to update value. If this value is string - value will be used as is. If it's array - will be called CHtml::normalizeUrl.
phaSelectColumn ¶
Because the column type phaSelectColumn is inherited from CDataColumn and CGridColumn, it includes entire set of properties and methods of base classes. Consider the different properties:
- data - data to build the drop-down list an array {id => name};
- modelId - name of models key. By default it's "id";
- actionUrl - see "Usage" section.
phaSelectColumn Example ¶
For example, consider building an interactive grid to edit a list of cities and time zones for this cities:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
...........
array (
'class' => 'phaSelectColumn',
'header' => 'Time Zone',
'name' => 'time_zone_id',
'data' => CHtml::listData(TimeZones::model()->findAll(), 'id', 'name'),
'actionUrl' => array('setTimeZone'),
),
...........
),
));
After changing any values will be send a POST request, containing:
- item - unique identifier of model
- value - selected value
phaCheckColumn ¶
For data that have two states is convenient use a column of phaCheckColumn type. In this column will display the checkbox when the status is change, the new value will be send to server.
phaCheckColumn Example ¶
For example, consider building an interactive grid to activate same item:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
...........
array(
'class' => 'phaCheckColumn',
'name' => 'is_active',
'actionUrl' => array('setIsActive'),
),
...........
),
));
After changing any values will be send a POST request, containing:
- item - unique identifier of model
- checked - 1 (if box is checked) or 0 (in another case).
phaEditColumn ¶
If you need edit text date without open other page, you can use this type of column. In normal state it's view data as ordinary column. But click on data cell will open input field for edit data. After press Enter new data will be send to server.
phaEditColumn Example ¶
We add column phaEditColumn type for editing attribute name of model.
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
...........
array(
'class' => 'phaCheckColumn',
'name' => 'name',
'actionUrl' => array('setName'),
),
...........
),
));
After changing any values will be send a POST request, containing:
- item - unique identifier of model;
- value - input data.
phaEditColumn usage ¶
If you click on row, view data will change to input field. Enter send data to server, and ESC-key will close input without send data.
bug in phaEditColumn
phaEditColumn is not working with several grids
Thx for extension!
re:bug in phaEditColumn
I'm not counting on such a possibility :) ок, I will include it in the coming version.
Thank you for using and reporting!
re:re:bug in phaEditColumn
I tried to fix it. Maybe it help you.
http://dl.dropbox.com/u/11392265/temp/phaEditColumn.php
ask: Could this work with CArrayDataProvider in the grid ?
hi, I think this is what I need.
Do you use it with CArrayDataProvider ?
Best Regards.
new version added
to lkg0dzre:
Thx for your version of the code, it helped me understand the problem.
The best way to add style to an element to be used in the configuration of the column:
array( 'class' => 'phaEditColumn', .... 'htmlEditFieldOptions' => array( 'style' => 'width: 100%' ), ),
to Nicolas400:
I use CActiveDataProvider. But I think CArrayDataProvider will not have problems with this extension, becouse it exted base column class only. If you have any problem with this extension - write report, I will fix it :)
New bug
Thank you very much for update!
But now i have another problem (= When i use several editable columns, working only last 'actionUrl' and name of column is don't send with ajax post. So i can have only one phaEditColumn in grid.
see on string 117
url: "' . $this->buildActionUrl() . '",
I tried to fix it. Maybe it help you again. http://dl.dropbox.com/u/11392265/temp/phaEditColumn.php
Also I add after 34 string
'style' => 'min-height: 2em',//++ for edit empty field
for edit empty field
And width: 100% needed for more big click-area
re: New bug
I have prepared a new version that solves this problem with different URL.
But I would like to clarify, does not solve the problem of empty fields use htmlOptions option for a cell?
re:re:New bug
I think it must work by default.
usign with CArrayDataProvider
HI, I tried with CArrayDataProvider, and don't fork for me.
First I see that the field is created with this id and class:
<div id="viewValue-yw1_c5-" class="viewValue-yw1_c5">
the id look not ok for me,
So i check inside phaEditColumn.php and I found this:
protected function renderDataCellContent($row,$data) { $value = CHtml::value($data, $this->name); $valueId = $data->{$this->modelId};
where $valueId is used to define the field ID:
echo CHtml::tag('div', array( 'valueid' => $valueId, 'id' => $fieldUID.'-'.$valueId, 'class' => $fieldUID ), $value);
I'll try to asign the field manually.
Regards.
re:re:New bug
'htmlOptions'=>array( 'style'=>'min-height: 2em;', ),
It isn't work.
It solved only by class in htmlOptions + css
phaEditColumn falling back to last url still
Hey there,
Just thought I'd let you know that the latest version still has issues with the url only working for one field.
But I think I know why, question is, how can we go about fixing it? First here's my entire widget call:
<?php $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'procedure-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( array( 'class' => 'phaEditColumn', 'name' => 'code', 'actionUrl' => array('setCode'), ), array( 'class' => 'phaEditColumn', 'name' => 'description', 'actionUrl' => array('setDescription'), ), array( 'class' => 'phaEditColumn', 'name' => 'price', 'actionUrl' => array('setPrice'), ), array( 'class'=>'CButtonColumn', 'template'=>'{update}{delete}' ), ), )); ?>
Now, the generated code that concerns me is:
phaACActionUrls["procedure-grid"]="/procedures/setCode"; jQuery(".viewValue-procedure-grid_c0").live("click", function(e){ phaACOpenEditField(this, "procedure-grid_c0"); return false; }); phaACActionUrls["procedure-grid"]="/procedures/setDescription"; jQuery(".viewValue-procedure-grid_c1").live("click", function(e){ phaACOpenEditField(this, "procedure-grid_c1"); return false; }); phaACActionUrls["procedure-grid"]="/procedures/setPrice"; jQuery(".viewValue-procedure-grid_c2").live("click", function(e){ phaACOpenEditField(this, "procedure-grid_c2"); return false; });
It appears to just override because the $data->grid->id is the same on all of them. When I switch this to $data->id, it starts posting to the same page the grids on, completely ignoring the url.
Any ideas? Thanks in advance!
Solved: Erroneously duplicated array keys for URL
Several others noted that phaEditColumn will submit the correct URL if used with only one column in the grid because the same key (grid id) is repeatedly used when populating the phaACActionUrls[] array. In comment #7902, jwerd (no relation to jward) was on the right track when $data->id was tried. It only takes a few more changes to complete a fix.
I modified the script in init(). You can spot my changes by finding the commented lines:
public function init() { parent::init(); $cs=Yii::app()->getClientScript(); $liveClick =' /* phaACActionUrls["'.$this->grid->id.'"]="' . $this->buildActionUrl() . '"; */ phaACActionUrls["'.$this->id.'"]="' . $this->buildActionUrl() . '"; jQuery(".'. $this->getViewDivClass() . '").live("click", function(e){ phaACOpenEditField(this, "' . $this->id . '"); return false; });'; $script =' var phaACOpenEditItem = 0; var phaACOpenEditGrid = ""; var phaACActionUrls = []; function phaACOpenEditField(itemValue, gridUID, grid ) { phaACHideEditField( phaACOpenEditItem, phaACOpenEditGrid ); var id = $(itemValue).attr("valueid"); $("#viewValue-" + gridUID + "-"+id).hide(); $("#field-" + gridUID + "-" + id).show(); $("#field-" + gridUID + "-" + id+" input") .focus() .keydown(function(event) { switch (event.keyCode) { case 27: phaACHideEditField( phaACOpenEditItem, gridUID ); break; case 13: /* phaACEditFieldSend( itemValue ); */ phaACEditFieldSend( itemValue, gridUID ); break; default: break; } }); phaACOpenEditItem = id; phaACOpenEditGrid = gridUID; } function phaACHideEditField( itemId, gridUID ) { var clearVal = $("#viewValue-" + gridUID + "-"+itemId).text(); $("#field-" + gridUID + "-" + itemId+" input").val( clearVal ); $("#field-" + gridUID + "-" + itemId).hide(); $("#field-" + gridUID + "-" + itemId+" input").unbind("keydown"); $("#viewValue-" + gridUID + "-" + itemId).show(); phaACOpenEditItem=0; phaACOpenEditGrid = ""; } /* function phaACEditFieldSend( itemValue ) { */ function phaACEditFieldSend( itemValue, gridUID ) { var id = $(itemValue).parents(".grid-view").attr("id"); $.ajax({ type: "POST", dataType: "json", cache: false, /* url: phaACActionUrls[id], */ url: phaACActionUrls[gridUID], data: { item: phaACOpenEditItem, value: $("#field-"+phaACOpenEditGrid+"-"+phaACOpenEditItem+" input").val() }, success: function(data){ $("#"+id).yiiGridView.update( id ); } }); } '; $cs->registerScript(__CLASS__.'#active_column-edit', $script); $cs->registerScript(__CLASS__.$this->grid->id.'#active_column_click-'.$this->id, $liveClick); }
Blank Fields are not Displayed and Cannot Be edited
It has been reported previously, but blank fields are not shown by phaEditColumn.
My solution was to substitute a "-" character in the displayed value. This is done in phaEditColumn.php
protected function renderDataCellContent($row,$data) { $value = CHtml::value($data, $this->name); if ($value=='') $value='-'; // Substitute a '-' character if field is blank $valueId = $data->{$this->modelId}; $this->htmlEditFieldOptions['itemId'] = $valueId; $fieldUID = $this->getViewDivClass(); echo CHtml::tag('div', array( 'valueid' => $valueId, 'id' => $fieldUID.'-'.$valueId, 'class' => $fieldUID ), $value); echo CHtml::openTag('div', array( 'style' => 'display: none;', 'id' => $this->getFieldDivClass() . $data->{$this->modelId}, )); echo CHtml::textField($this->name.'[' . $valueId . ']', $value, $this->htmlEditFieldOptions); echo CHtml::closeTag('div'); }
Make field width equal to td width.
This is what I did to make input field respect td width (lines commented as new).
function phaACOpenEditField(itemValue, gridUID, grid ) { phaACHideEditField( phaACOpenEditItem, phaACOpenEditGrid ); var id = $(itemValue).attr("valueid"); //new start var width = $(itemValue).closest("td").attr("width"); //fix for IE because it is providing width:20 instead of width:20px in td. if(typeof width !== "undefined"){ if(width.indexOf("px", width.length - 2) === -1){ width += "px"; } } //new end $("#viewValue-" + gridUID + "-"+id).hide(); $("#field-" + gridUID + "-" + id).show(); $("#field-" + gridUID + "-" + id+" input") .attr("style", "width:"+width+";text-align:right") //new .focus() .keydown(function(event) { switch (event.keyCode) { case 27: phaACHideEditField( phaACOpenEditItem, gridUID ); break; case 13: phaACEditFieldSend( itemValue ); break; default: break; } }); phaACOpenEditItem = id; phaACOpenEditGrid = gridUID; }
And this is an example of a grid column declared in the view.
array( 'name'=>'payment', 'class'=>'phaEditColumn1', 'actionUrl' => array('uncollected/setAttribute', 'attribute'=>'payment'), 'htmlOptions'=>array('width'=>'70px', 'style'=>'text-align:right'), 'headerHtmlOptions'=>array('width'=>'70px'), ),
jQuery .live deprecated
The jQuery function ".live" has been deprecated. Use ".on" instead.
Change phaEditColumn.php
$liveClick =' /* phaACActionUrls["'.$this->grid->id.'"]="' . $this->buildActionUrl() . '"; */ phaACActionUrls["'.$this->id.'"]="' . $this->buildActionUrl() . '"; jQuery(".'. $this->getViewDivClass() . '").on("click", null, function(e){ phaACOpenEditField(this, "' . $this->id . '"); return false; });';
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.