YiiWheels
  • Package
  • Class
  • Tree

Packages

  • None
  • yiiwheels
    • behaviors
    • widgets
    • widgets
      • ace
      • box
      • datepicker
      • daterangepicker
      • datetimepicker
      • detail
      • fileupload
      • fileuploader
      • gallery
      • google
      • grid
        • behaviors
        • operations
      • highcharts
      • maskInput
      • maskmoney
      • modal
      • multiselect
      • rangeslider
      • redactor
      • select2
      • sparklines
      • switch
      • timeago
      • timepicker
      • toggle
      • typeahead

Classes

  • WhGridView
  • WhGroupGridView
  • WhImageColumn
  • WhRelationalColumn
  1 <?php
  2 /**
  3  * WhRelationalColumn class
  4  *
  5  * Displays a clickable column that will make an ajax request and display its resulting data
  6  * into a new row.
  7  *
  8  * @author Antonio Ramirez <amigo.cobos@gmail.com>
  9  * @copyright Copyright &copy; 2amigos.us 2013-
 10  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 11  * @package YiiWheels.widgets.grid
 12  * @uses Yiistrap.widgets.TbDataColumn
 13  */
 14 Yii::import('bootstrap.widgets.TbDataColumn');
 15 
 16 class WhRelationalColumn extends TbDataColumn
 17 {
 18     /**
 19      * @var string $url the route to call via AJAX to get the data from
 20      */
 21     public $url;
 22 
 23     /**
 24      * @var string $cssClass the class name that will wrap up the cell content.
 25      * Important Note: this class will be used as the trigger for the AJAX call, so make sure is unique for the
 26      * column.
 27      */
 28     public $cssClass = 'wh-relational-column';
 29 
 30     /**
 31      * @var bool $cacheData if set to true, there won't be more than one AJAX request. If set to false, the widget will
 32      * continuously make AJAX requests. This is useful if the data could vary. If the data doesn't change then is better
 33      * to set it to true. Defaults to true.
 34      */
 35     public $cacheData = true;
 36 
 37     /**
 38      * @var string a javascript function that will be invoked if an AJAX call occurs.
 39      *
 40      * The function signature is <code>function(tr, rowid, data)</code>
 41      * <ul>
 42      * <li><code>tr</code> is the newly created TR HTML object that will display the returned server data.</li>
 43      * <li><code>rowid</code> the model id of the row.</li>
 44      * <li><code>data</code> is the data returned by the server that is already displayed on the row.</li>
 45      * </ul>
 46      * Note: This handler is not called for JSONP requests.
 47      *
 48      * Example (add in a call to TbRelationalColumn):
 49      * <pre>
 50      *  ...
 51      *  'afterAjaxUpdate'=>'js:function(tr,rowid, data){ console.log(rowid); }',
 52      *  ...
 53      * </pre>
 54      */
 55     public $afterAjaxUpdate;
 56 
 57     /**
 58      * @var string $ajaxErrorMessage the message that is displayed on the newly created row in case there is an AJAX
 59      * error.
 60      */
 61     public $ajaxErrorMessage = 'Error';
 62 
 63     /**
 64      * widget initialization
 65      */
 66     public function init()
 67     {
 68         parent::init();
 69 
 70         if (empty($this->url))
 71             $this->url = Yii::app()->getRequest()->requestUri;
 72 
 73         $this->attachBehavior('ywplugin', array('class' => 'yiiwheels.behaviors.WhPlugin'));
 74         $this->registerClientScript();
 75     }
 76 
 77     /**
 78      * Overrides CDataColumn renderDataCell in order to wrap up its content with the object that will be used as a
 79      * trigger.
 80      * Important: Making use of links as a content for this of column is an error.
 81      * @param int $row
 82      */
 83     public function renderDataCell($row)
 84     {
 85         $data    = $this->grid->dataProvider->data[$row];
 86         $options = $this->htmlOptions;
 87         if ($this->cssClassExpression !== null) {
 88             $class = $this->evaluateExpression($this->cssClassExpression, array('row' => $row, 'data' => $data));
 89             if (isset($options['class']))
 90                 $options['class'] .= ' ' . $class;
 91             else
 92                 $options['class'] = $class;
 93         }
 94         echo CHtml::openTag('td', $options);
 95         echo CHtml::openTag('span', array('class' => $this->cssClass, 'data-rowid' => $this->getPrimaryKey($data)));
 96         $this->renderDataCellContent($row, $data);
 97         echo '</span>';
 98         echo '</td>';
 99     }
100 
101     /**
102      * Helper function to return the primary key of the $data
103      *  * IMPORTANT: composite keys on CActiveDataProviders will return the keys joined by comma
104      * @param CActiveRecord $data
105      * @return null|string
106      */
107     protected function getPrimaryKey($data)
108     {
109         if ($this->grid->dataProvider instanceof CActiveDataProvider) {
110             $key = $this->grid->dataProvider->keyAttribute === null ? $data->getPrimaryKey(
111             ) : $data->{$this->keyAttribute};
112             return is_array($key) ? implode(',', $key) : $key;
113         }
114         if ($this->grid->dataProvider instanceof CArrayDataProvider || $this->grid->dataProvider instanceof CSqlDataProvider)
115             return is_object(
116                 $data
117             ) ? $data->{$this->grid->dataProvider->keyField} : $data[$this->grid->dataProvider->keyField];
118 
119         return null;
120     }
121 
122     /**
123      * Register script that will handle its behavior
124      */
125     public function registerClientScript()
126     {
127         $path = __DIR__ . DIRECTORY_SEPARATOR . 'assets';
128         $assetsUrl = $this->getAssetsUrl($path);
129 
130         /** @var $cs CClientScript */
131         $cs = Yii::app()->getClientScript();
132         $cs->registerCssFile($assetsUrl . '/css/bootstrap-relational.css');
133 
134         if ($this->afterAjaxUpdate !== null) {
135             if ((!$this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos(
136                     $this->afterAjaxUpdate,
137                     'js:'
138                 ) !== 0
139             )
140                 $this->afterAjaxUpdate = new CJavaScriptExpression($this->afterAjaxUpdate);
141         } else
142             $this->afterAjaxUpdate = 'js:$.noop';
143 
144         $this->ajaxErrorMessage = CHtml::encode($this->ajaxErrorMessage);
145         $afterAjaxUpdate        = CJavaScript::encode($this->afterAjaxUpdate);
146         $span                   = count($this->grid->columns);
147         $loadingPic             = CHtml::image(Yii::app()->yiiwheels->getAssetsUrl() . '/img/loading.gif');
148         $cache                  = $this->cacheData ? 'true' : 'false';
149         $data                   = !empty($this->submitData) && is_array(
150             $this->submitData
151         ) ? $this->submitData : 'js:{}';
152         $data                   = CJavascript::encode($data);
153 
154         $js = <<<EOD
155 $(document).on('click','.{$this->cssClass}', function(){
156     var span = $span;
157     var that = $(this);
158     var status = that.data('status');
159     var rowid = that.data('rowid');
160     var tr = $('#relatedinfo'+rowid);
161     var parent = that.parents('tr').eq(0);
162     var afterAjaxUpdate = {$afterAjaxUpdate};
163 
164     if (status && status=='on'){return}
165     that.data('status','on');
166 
167     if (tr.length && !tr.is(':visible') && {$cache})
168     {
169         tr.slideDown();
170         that.data('status','off');
171         return;
172     }else if (tr.length && tr.is(':visible'))
173     {
174         tr.slideUp();
175         that.data('status','off');
176         return;
177     }
178     if (tr.length)
179     {
180         tr.find('td').html('{$loadingPic}');
181         if (!tr.is(':visible')){
182             tr.slideDown();
183         }
184     }
185     else
186     {
187         var td = $('<td/>').html('{$loadingPic}').attr({'colspan':$span});
188         tr = $('<tr/>').prop({'id':'relatedinfo'+rowid}).append(td);
189         /* we need to maintain zebra styles :) */
190         var fake = $('<tr class="hide"/>').append($('<td/>').attr({'colspan':$span}));
191         parent.after(tr);
192         tr.after(fake);
193     }
194     var data = $.extend({$data}, {id:rowid});
195     $.ajax({
196         url: '{$this->url}',
197         data: data,
198         success: function(data){
199             tr.find('td').html(data);
200             that.data('status','off');
201             if ($.isFunction(afterAjaxUpdate))
202             {
203                 afterAjaxUpdate(tr,rowid,data);
204             }
205         },
206         error: function()
207         {
208             tr.find('td').html('{$this->ajaxErrorMessage}');
209             that.data('status','off');
210         }
211     });
212 });
213 EOD;
214         $cs->registerScript(__CLASS__ . '#' . $this->id, $js);
215     }
216 }
217 
YiiWheels API documentation generated by ApiGen 2.8.0