Editable
Creates single editable element. Serves mainly as base class for other widgets.
Example
Widget source
<?php
$this->widget('editable.Editable', array(
'type' => 'text',
'name' => 'user_name',
'pk' => 1,
'text' => 'John',
'url' => $this->createUrl('site/updateUser'),
'title' => 'Enter user name',
'placement' => 'right'
));
?>
EditableField
Makes editable single attribute of model. Attribute should be safe (e.g. defined in rules() method of model)
It can be one of several types:
1. Text
Example
(try empty value to test validation)
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'text',
'model' => $user,
'attribute' => 'user_name',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
));
?>
In model User.php
public function rules()
{
return array(
array('user_name', 'required'), //make user_name safe and required
...
);
}
2. Textarea
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'textarea',
'model' => $user,
'attribute' => 'user_comment',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
'showbuttons' => 'bottom',
));
?>
3. Select (load items from array)
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'select',
'model' => $user,
'attribute' => 'user_status',
'url' => $this->createUrl('site/updateUser'),
'source' => CHtml::listData(Status::model()->findAll(), 'status_id', 'status_text'),
'placement' => 'right',
));
?>
4. Select (load items from url)
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'select',
'model' => $user,
'attribute' => 'user_status_ext',
'url' => $this->createUrl('site/updateUser'),
//since 1.1.0 source must be string for remote loading (not array Yii route!)
'source' => $this->createUrl('site/getStatusList'),
'placement' => 'right',
));
?>
Action site/GetStatusList
public function actionGetStatusList()
{
echo CJSON::encode(CHtml::listData(Status::model()->findAll(), 'status_id', 'status_text'));
}
5. Date
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'date',
'model' => $user,
'attribute' => 'user_dob',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
'viewformat' => 'dd/mm/yyyy'
));
?>
In model rules()
array('user_dob', 'default', 'value' => null), //make user_dob safe and convert "" to null
i18n:
For Bootstrap datepicker you should include lang file from here and set option language
$this->widget('editable.EditableField', array(
...
'options' => array(
'datepicker' => array('language' => 'ru')
)
));
Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl.'/js/bootstrap-datepicker.ru.js', CClientScript::POS_END);
For jQuery UI datepicker you just should include lang file from here.
Yii::app()->clientScript->registerScriptFile(Yii::app()->baseUrl.'/js/jquery.ui.datepicker-ru.js', CClientScript::POS_END);
6. Datetime (bootstrap only!)
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'datetime',
'model' => $user,
'attribute' => 'user_visit',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
'format' => 'yyyy-mm-dd hh:ii',
'viewformat' => 'dd/mm/yyyy hh:ii',
));
?>
In model rules()
array('user_visit', 'default', 'value' => null), //make attribute safe and convert "" to null
7. Combodate
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'combodate',
'model' => $user,
'attribute' => 'user_reserve',
//define value directly as it should match the format
'value' => isset($user->user_visit) ? date('Y-m-d H:i', strtotime($user->user_visit)) : '',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
'format' => 'YYYY-MM-DD HH:mm', //in this format date sent to server
'viewformat' => 'MMM DD, YYYY HH:mm', //in this format date is displayed
'template' => 'DD / MMM / YYYY HH:mm', //template for dropdowns
'combodate' => array('minYear' => 1980, 'maxYear' => 2013),
));
?>
In model rules()
array('user_reserve', 'default', 'value' => null), //make attribute safe and convert "" to null
8. Checklist
Example
Widget source
<?php
$this->widget('editable.EditableField', array(
'type' => 'checklist',
'model' => $user,
'attribute' => 'user_params',
'placement' => 'right',
'url' => $this->createUrl('site/updateUser'),
'source' => array('pretty', 'awesome', 'smart', 'ambitious'),
));
?>
In model User.php
public function rules()
{
return array(
array('user_params', 'implodeParams'), //define custom validator to implode checked values into string
...
);
}
public function implodeParams($attribute)
{
if(is_array($this->$attribute)) {
$this->$attribute = implode(',', $this->$attribute); //in db it is stored as string e.g. '1,3,4'
}
}
9. Select2
Example
Widget source
<?php
$tags = array(
array('id' => 1, 'text' => 'php'),
array('id' => 2, 'text' => 'html'),
array('id' => 3, 'text' => 'css'),
array('id' => 4, 'text' => 'javascript'),
);
$this->widget('editable.EditableField', array(
'type' => 'select2',
'model' => $user,
'attribute' => 'user_tags',
'url' => $this->createUrl('site/updateUser'),
'source' => $tags,
'placement' => 'right',
'select2' => array(
'multiple' => true
)
));
?>
In model rules()
public function rules()
{
return array(
array('user_tags', 'implodeParams'), //define custom validator to implode checked values into string
...
);
}
public function implodeParams($attribute)
{
if(is_array($this->$attribute)) {
$this->$attribute = implode(',', $this->$attribute); //in db it is stored as string e.g. '1,3,4'
}
}
EditableDetailView
Makes editable several attributes of single model, shown as name-value table.
Just define editable section inside attribute config. Only safe attributes become editable.
1. Existing record
| User Name | yiiuser |
|---|---|
| Group | |
| Status | |
| Date of birth | |
| Language | France |
| Comment | No comments.. |
| Created | 2012-09-09 01:26:06 |
Source (equal for both cases)
<?php
$this->widget('editable.EditableDetailView', array(
'data' => $user,
//you can define any default params for child EditableFields
'url' => $this->createUrl('site/updateUser'), //common submit url for all fields
'params' => array('YII_CSRF_TOKEN' => Yii::app()->request->csrfToken), //params for all fields
'emptytext' => 'no value',
'attributes' => array(
array(
'name' => 'user_name',
'editable' => array(
'type' => 'text',
'inputclass' => 'input-large',
'emptytext' => 'special emptytext',
'validate' => 'function(value) {
if(!value) return "User Name is required (client side)"
}'
)
),
array( //select loaded from database
'name' => 'group_id',
'editable' => array(
'type' => 'select',
'source' => CHtml::listData(Group::model()->findAll(), 'group_id', 'group_name')
)
),
array( //select loaded from ajax.
'name' => 'user_status',
'editable' => array(
'type' => 'select',
'source' => $this->createUrl('site/getStatuses'),
)
),
array(
'name' => 'user_dob',
'editable' => array(
'type' => 'date',
'viewformat' => 'dd/mm/yyyy'
)
),
array( //edit related record
'name' => 'profile.language',
'editable' => array(
'url' => array('site/updateProfile') //related record requires own submit url
)
),
'user_comment',
'created_at', //not editable as attribute is not safe
)
));
?>
For new record you just pass to widget instance of new model, e.g. $user = new User;.
When you click on Save button all values are collected, validated and submitted to server (you can find more details here).
Onclick handler can be set as following:
<? if($user->isNewRecord) {
Yii::app()->clientScript->registerScript('new-user', '
$("#save-btn").click(function() {
$(this).parent().parent().find(".editable").editable("submit", {
url: "'.$this->createUrl('site/createUser').'",
ajaxOptions: { dataType: "json" },
success: function(data, config) {
if(data && data.id) {
$(this).editable("option", "pk", data.id);
$(this).removeClass("editable-unsaved");
$("#msg").removeClass("alert-error").addClass("alert-success")
.html("User created! Now you can update it.").show();
$("#save-btn").hide();
} else {
config.error.call(this, data && data.errors ? data.errors : "Unknown error");
}
},
error: function(errors) {
var msg = "";
if(errors && errors.responseText) {
msg = errors.responseText;
} else {
$.each(errors, function(k, v) { msg += v+"<br>"; });
}
$("#msg").removeClass("alert-success").addClass("alert-error")
.html(msg).show();
}
});
});
');
}
?>
Server-side action to create new record:
public function actionCreateUser()
{
if(Yii::app()->request->isPostRequest) {
$model = new User;
$model->attributes = $_POST;
if($model->save()) {
echo CJSON::encode(array('id' => $model->primaryKey));
} else {
$errors = array_map(function($v){ return join(', ', $v); }, $model->getErrors());
echo CJSON::encode(array('errors' => $errors));
}
} else {
throw new CHttpException(400, 'Invalid request');
}
}
EditableColumn
Makes editable one column in GridView. Grid stays editable after ajax sorting and pagination.
Parameters are defined in editable section of column config.
Since 1.1 works with both CActiveDataProvider and CArrayDataProvider.
Example
| User Name | Status | Date of birth | Comment |
|---|---|---|---|
| superuser | Awesome user! | ||
| yiiuser | No comments.. | ||
| user3 |
Source
<? $this->widget('bootstrap.widgets.TbGridView', array(
'id' => 'user-grid',
'itemsCssClass' => 'table-bordered',
'dataProvider' => $dataProvider,
'columns'=>array(
array(
'class' => 'editable.EditableColumn',
'name' => 'user_name',
'headerHtmlOptions' => array('style' => 'width: 110px'),
'editable' => array( //editable section
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
)
),
array(
'class' => 'editable.EditableColumn',
'name' => 'user_status',
'headerHtmlOptions' => array('style' => 'width: 100px'),
'editable' => array(
'type' => 'select',
'url' => $this->createUrl('site/updateUser'),
'source' => $this->createUrl('site/getStatuses'),
'options' => array( //custom display
'display' => 'js: function(value, sourceData) {
var selected = $.grep(sourceData, function(o){ return value == o.value; }),
colors = {1: "green", 2: "blue", 3: "red", 4: "gray"};
$(this).text(selected[0].text).css("color", colors[value]);
}'
),
//onsave event handler
'onSave' => 'js: function(e, params) {
console && console.log("saved value: "+params.newValue);
}'
)
),
array(
'class' => 'editable.EditableColumn',
'name' => 'user_dob',
'headerHtmlOptions' => array('style' => 'width: 100px'),
'editable' => array(
'type' => 'date',
'viewformat' => 'dd.mm.yyyy',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'right',
)
),
array(
'class' => 'editable.EditableColumn',
'name' => 'user_comment',
'editable' => array(
'type' => 'textarea',
'url' => $this->createUrl('site/updateUser'),
'placement' => 'left',
)
),
),
));
?>
Options
These options are passed as configuration array into EditableField or into editable section of EditableDetailView and EditableColumn.
Please refer to X-editable docs for the most detailed description (options marked with x-editable).
| Name | Type | Default | Description | Related |
|---|---|---|---|---|
| apply | boolean | null | whether to apply 'editable' js plugin to element. Only safe attributes become editable. | Yii |
| attribute | string | required | attribute name. | Yii |
| cssFile | mixed | 'jquery-ui.css' | for jQuery UI only. The theme CSS file name. By default Yii's jquery UI css used. | Yii |
| disabled | boolean | false | will editable be initially disabled. It means editable plugin will be applied to element, but you should call .editable('enable') method to activate it. To totally disable applying 'editable' to element use apply option. | x-editable |
| emptytext | string | null | text shown on empty field. If null - default X-editable value is used: Empty | x-editable |
| encode | boolean | true | whether to HTML encode text on output | Yii |
| format | string | null | format to send date on server. If null - default X-editable value is used: yyyy-mm-dd. | x-editable |
| htmlOptions | array | array() | HTML options of element | Yii |
| inputclass | string | null | css class of input. If null - default X-editable value is used: input-medium | x-editable |
| mode | string | null | mode of input: inline | popup. If not set - default X-editable value is used: popup. | x-editable |
| model | CActiveRecord | required | ActiveRecord to be updated. | Yii |
| name* | string | null | name of field | x-editable |
| options | array | array() | all config options of x-editable. See full list here. | Yii |
| params | array | null | additional params to send on server | x-editable |
| pk* | mixed | null | primary key | x-editable |
| placement | string | null | placement of popup. Can be left, top, right, bottom. If null - default X-editable value is used: top | x-editable |
| showbuttons | string | null | visibility of buttons. Can be boolean false|true or string bottom. | x-editable |
| source | mixed | null | source data for select, checklist. Can be string (url) or array in format: array( array("value" => 1, "text" => "abc"), ...) | x-editable |
| text* | string | null | text to be shown as element content | Yii |
| theme | string | 'base' | for jQuery UI only. The JUI theme name. | Yii |
| themeUrl | string | for jQuery UI only. The root URL that contains JUI theme folders. If not set, default Yii's theme will be used. | Yii | |
| title | string | null | title of popup. If null - will be generated automatically from attribute label. Can have token {label} inside that will be replaced with actual attribute label. | Yii |
| type | string | null | type of editable widget. Can be text, textarea, select, date, checklist, etc. | x-editable |
| url | string | null | url to submit value. Can be string or array containing Yii route, e.g. array('site/updateUser') | x-editable |
| value | mixed | null | initial value. If not set - will be taken from text | x-editable |
| viewformat | string | null | format to display date in element. If null - equals to format option. | x-editable |
* - required only for raw Editable class. Not used for other classes as CModel provides these data automatically.
Callbacks
| Name | Description | Related |
|---|---|---|
| validate | A javascript function that will be invoked to validate value. Example:
'validate' => 'js: function(value) {
if($.trim(value) == "") return "This field is required";
}'
| x-editable |
| success | A javascript function that will be invoked to process successful server response. Example:
'success' => 'js: function(response, newValue) {
if(!response.success) return response.msg;
}'
| x-editable |
| display | A javascript function that will be invoked to custom display value. Example:
'display' => 'js: function(value, sourceData) {
var escapedValue = $("<div>").text(value).html();
$(this).html("<b>"+escapedValue+"</b>");
}'
| x-editable |
Events
Please see also Events tab of X-editable docs.
| Name | Description | Related |
|---|---|---|
| onInit | A javascript function that will be invoked when editable element is initialized | x-editable |
| onShown | A javascript function that will be invoked when editable form is shown
Example:
'onShown' => 'js: function() {
var $tip = $(this).data("editableContainer").tip();
$tip.find("input").val("overwriting value of input.");
}'
| x-editable |
| onSave | A javascript function that will be invoked when new value is saved
Example:
'onSave' => 'js: function(e, params) {
alert("Saved value: " + params.newValue);
}'
| x-editable |
| onHidden | A javascript function that will be invoked when editable form is hidden
Example:
'onHidden' => 'js: function(e, reason) {
if(reason === "save" || reason === "cancel") {
//auto-open next editable
$(this).closest("tr").next().find(".editable").editable("show");
}
}'
| x-editable |