Editable Field

Inline editing of the textual data

This widget makes the text string which can be edited by clicking on it and entering new value, using either popup or inline text field. This can be used to make quasi-interactive documents containing placeholders, for example.

Simplest possible usage of the widget is this:

$this->widget(
    'booster.widgets.TbEditableField',
    array(
        'type' => 'text',
        'model' => $model,
        'attribute' => 'name', // $model->name will be editable
        'url' => $endpoint, //url for submit data
    )
);

Note In this example we are using the Region ActiveRecord class which is backed by real table in our DB. Records are fetched randomly (try reloading this page).

Hint Try opening the Development Tools in your browser and look what request are being sent when you edit the value and press "OK".

For simplicity, you can think that $model widget config parameter accepts just the CActiveRecord instances loaded with data about some existing database record. But if you don't need or want to use CActiveRecord check out the section Forging objects to be made editable below.

Here is all parameters you can pass when creating the TbEditableField widget instance.

Property Description
CActiveRecord model = null Object which attribute named in attribute will be made editable. This widget is designed to work with CActiveRecord instances, but it's not mandatory. Check the section Forging objects to be made editable for details.
string attribute = null The name of attribute to be made editable. Please note that this attribute should be marked as "safe" in CModel.rules, i. e., there should be some rule defined for this attribute (of course, not the "safe", "safe" => false one).
string type = null

Type of the input with which you will enter the values of the attribute. As of X-Editable 1.4.5 supported values are text, textarea, select, select2, date, datetime, dateui, combodate, checklist, typeahead, html5types and wysihtml5. See official documentation for X-Editable types for details.

If your model is CActiveRecord and this property is null then widget will try to guess the type based on database metadata for attribute in question.

If you fake the model object and do not set the type explicitly, you can end up faking CActiveRecord.tableSchema, too.

string|array url = null Url to submit value to. If it is an array, it should be in format acceptable by CHtml::normalizeUrl(not the CController.createUrl).
array params = null Additional params to send to server, in name=>value format. This values will be sent alongside with the mandatory values sent by X-Editable by default (which are "pk", "name" and "value"), i. e., using same HTTP method (POST by default). See original documentation for X-Editable parameters for details.
string mode = "popup" Mode of editable input. Can be "inline" or "popup". Even if you explicitly null this attribute, default is "popup".
string placement = "top" Placement of the popup (this property is ignored for inline editables). Even if you explicitly null this attribute, default is "top".
boolean disabled = false Should this editable field be initially disabled. It means "editable" plugin will be applied to element, but you should call `.editable("enable")` method to activate it. To completely disable applying "editable" to element use `apply` option.
boolean apply = true Should this field be non-editable. If you set `apply` to false, widget will render just a text label and will not include any javascript libraries.
string emptytext = "Empty" What to render when the editable value is null.
string text = null What to render initially. If `text` is not explicitly set, EditableField will behave in obvious way: will render the current value of `model`.`attribute`.
string value = null Initial value of the field. As opposing to `text` attribute, `value` is the real value which will be sent to server on updates. Difference between `text` and `value` is the same as when you create HTML dropdown list elements.
array htmlOptions = array() Traditional array with HTML attributes which should be applied to the link which triggers the editable behavior.
array options = array() Here you can directly specify any option accepted by X-Editable plugin. This array will be JSON-encoded. See full list at official documentation for X-Editable.
boolean encode = true Whether to HTML-encode the text before render.
string title = null Title for popup. For inline editable fields is ignored, of course. If set to `null`, title will be generated automatically from attribute label.
string|array source = null

Note Applicable only when type equal to checklist and select.

If it is an array, then its elements should be arrays in format array("value" => "somevalue", "text" => "sometext").

If it is a function, then it should return an array in the previously mentioned format.

If it is a string, then it is treated like an URL to some AJAX endpoint returning the JSON-encoded array representation described above.

string format = null

Note Applicable only when type equal to date.

Date format in which to send date values to server. If null then equals to yyyy-mm-dd.

Recognized tokens are d, dd, m, mm, yy, yyyy

This property corresponds to the format property of the X-Editable date inputs.

string viewformat = null

Note Applicable only when type equal to date.

Date format in which to show the date on the web page. If null then equals to the value of format property.

Recognized tokens are d, dd, m, mm, yy, yyyy

This property corresponds to the viewformat property of the X-Editable date inputs.

string template = null

Note Applicable only when type equal to combodate.

Template for combodate inputs.

For details see original documentation for X-Editable combodate inputs.

array combodate = null

Note Applicable only when type equal to combodate.

Full config tree for combodate inputs.

For details see original documentation for combodate widget.

string viewseparator = null

Note Applicable only when type equal to select2.

Separator used to display tags.

array select2 = null

Note Applicable only when type equal to select2.

Full config tree for select2 inputs.

For details see original documentation for select2 widget.

string parent = null

Deprecated This property will be removed in next backwards-incompatible release.

Historically, this property was designed to speed up the application of a plugin a bit, by selecting a direct parent of the target element to be made X-Editable in DOM tree. But, honestly, just do not use this property, it has no real visible effect anyway.

string inputclass = "input-medium" CSS class of the input. If null then will be re-set to "input-medium".
string validate = null

A javascript function that will be invoked to validate value.

Example:

'validate' => 'js: function(value) {
  if ($.trim(value) == "") 
    return "This field is required";
}'
string success = null

A javascript function that will be invoked to process successful server response.

Example:

'success' => 'js: function(response, newValue) {
  if (!response.success) 
    return response.msg;
}'
string display = null

A javascript function that will be invoked to customize displaying of a value.

Example:

'display' => 'js: function(value, sourceData) {
  var escapedValue = $("<div>").text(value).html();
  $(this).html("<b>" + escapedValue + "</b>")
}'
string onInit = null

A javascript function that will be invoked when editable field will be initialized.

Example:

'onInit' => 'js: function(event, editable) {
  console.debug("X-Editable field " + editable.options.name + " ready to serve.");
}'
string onShown = null

A javascript function that will be invoked when editable form (popup or inline) is shown.

Example:

'onShown' => 'js: function(event) {
  var tip = $(this).data("editableContainer").tip();
  tip.find("input").val("overwriting value of input.");}'
string onHidden = null

A javascript function that will be invoked when editable form is hidden.

Example:

'onHidden' => 'js: function(event, reason) {
  if (reason === "save" || reason === "cancel") {
    // auto-open next editable
    $(this).closest("tr").next().find(".editable").editable("show");
  }
}'
string onSave = null

A javascript function that will be invoked when new value is saved.

Example:

'onSave' => 'js: function(event, params) {
  console.debug("Saved value: " + params.newValue);
}'

Here will be presented some examples of Editable Field usage.

Note This time to speed things up no real ActiveRecords bound to database tables will be used. All models are fake in-memory ones, as described in "Faking" section below.

Text

$this->widget('booster.widgets.TbEditableField', array(
    'type' => 'text',
    'model' => $model,
    'attribute' => 'someStringAttribute',
    'url' => $endpoint, //url for submit data
));

Textarea

$this->widget('booster.widgets.TbEditableField', array(
    'type' => 'textarea',
    'model' => $model,
    'attribute' => 'someLongStringAttribute',
    'url' => $endpoint, //url for submit data
    'placement' => 'right'
));

Select

$this->widget('booster.widgets.TbEditableField', array(
    'type' => 'select2',
    'model' => $model,
    'attribute' => 'someEnumerableAttribute',
    'url' => $endpoint, //url for submit data
    'source' => array('Choose', 'your', 'destiny', '.')
));

Date

$this->widget(
    'booster.widgets.TbEditableField',
    array(
        'type' => 'date',
        'model' => $model,
        'attribute' => 'someDateAttribute',
        'url' => $endpoint, //url for submit data
        'placement' => 'right',
        'format' => 'yyyy-mm-dd',
        'viewformat' => 'mm/dd/yyyy',
        'options' => array(
            'datepicker' => array(
                'language' => 'ru'
            )
        )
    )
);

Note As you probably can see, even if Editable Field has language explicitly declared, its datepicker is still in English. This is a known bug and it'll be resolved one day.

This widget is designed to work with CActiveRecord descendant class instances, but in fact any CModel inheritors will do. Here's the strict requirements for the model passed as $model in the example above:

  • It should be "not new", i. e., it should have a property named isNewRecord having the value of false.
  • It should have primary key defined which has a non-empty value, i. e:
    • It should have some attribute like id which should hold the value of primary key.
    • It should have a primaryKey attribute holding the name of this "primary key" attribute.
  • It should have a isAttributeSafe method which returns true when passed the name of the attribute in question.
  • It should have a getAttributeLabel method which returns some human-readable label for the name of the attribute in question.

So, here's the example usage of complete fake which will be accepted by the TbEditableField widget:

class FakeActiveRecord
{
    public $isNewRecord = false;
    public $primaryKey = 'myid';
    public $myid;
    public $myattr;

    public function isAttributeSafe()
    {
        return true;
    }

    public function getAttributeLabel()
    {
        return 'Text Field';
    }
    
    public function getScenario() {
    	return 'update';
    }
}

$model = new FakeActiveRecord;
$model->myid = 1;
$model->myattr = 'Lorem Ipsum!';

$this->widget(
    'booster.widgets.TbEditableField',
    array(
        'type' => 'text',
        'model' => $model,
        'attribute' => 'myattr',
        'url' => $endpoint, //url for submit data
    )
);

Important If you are going to fake editable fields of types select2, select, date, dateui, checklist or combodate, you will have to fake an additional method: getAttribute($attr). It should return the value of the $attr attribute.

Important If you not set the type property of this widget at all or deliberately set it to null, this widget will try to guess the type based on the metadata of the DB column. You will end up faking the whole CActiveRecord.tableSchema.