Yii 1.1: asteroid

Quickly Add Dynamic Content Without Writing JS Or Additional Actions! Quickly bind JQuery events and much more
11 followers
Example 1: Using replace() append() And prepend()
Example 2: Dynamically Rendering An Yii Grid View
Exmaple 3: Using onEvent()
Exmaple 4: Using sendVars()
Exmaple 5: Using useBelt()

Yii Extension: Quickly Add Dynamic Content Without Writing JS Or Additional Actions! Quickly bind JQuery events and much more… In other words Asteroid gives the ability to lazy load your partials either on load or bound to events like 'click' or 'mouseenter'.

Requirements

  1. Yii 1.8 or above
  2. PHP 5.3 or above

Installation

  1. Place the Asteroid directory in protected/extensions
  2. In your desired Controller Class add the Asteroid behavior like so:
class MyController extends Controller
{
    public function behaviors() {
       return array('EAsteroid' =>
           array('class'=>'ext.Asteroid.behaviors.EAsteroid')
       );
    }}

Usage

For purposes of the following examples we will assume we have the below controller and views:

controllers/SampleController.php

class sampleController extends Controller
{
    public function behaviors() {
        return array('EAsteroid' => array('class' => 'ext.Asteroid.behaviors.EAsteroid'));
    }public function actionTestUI()
    {$this->render('index');
    }}

views/sample/index.php

<div id="clickMe">Click Here</div>
 
<div id="myDiv1">
 
</div>
 
 
<div id="myDiv2">
 
</div>
 
 
<div id="myDiv3">
 
</div>

/views/sample/_p1.php

<h1><?php echo $var1; ?></h1>
<h2><?php echo $var2; ?></h1>

/views/sample/_p2.php

<h1><?php echo $var3; ?></h1>
<h2><?php echo $var4; ?></h1>

/views/sample/p3GridView.php

<?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'airport-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'columns'=>array(
        'id',
        'sample_code',
        'name',
        array(
            'class'=>'CButtonColumn',
        ),
    ),
)); ?>

Example 1: Using replace() append() And prepend()

Lets say we want to dynamically load the content of the partial view _p1.php into the div "#myDiv1" of test view.

public function actionTestUI()
{
    $this->asteroid('a1')
            ->replace('#myDiv1', '_p1', function(){ return array('var1'=>'Yeah!', 'var2'=>'Thats right!'); })
    ->orbit();
 
    $this->render('test');
}

Now lets say we have the same scenario but we would also like to append some content to the div "#myDiv2"

public function actionTestUI()
{
    $this->asteroid('a1')
            ->replace('#myDiv1', '_p1', function(){ return array('var1'=>'Yeah!', 'var2'=>'Thats right!'); })
         ->asteroid('a2')
            ->append('#myDive2', '_p2', function(){ return array('var3'=>'Im Here!', 'var4'=>'You know it!'); })
    ->orbit();
 
    $this->render('test');
}

We could also have chosen to prepend

public function actionTestUI()
{
    $this->asteroid('a1')
            ->replace('#myDiv1', '_p1', function(){ return array('var1'=>'Yeah!', 'var2'=>'Thats right!'); })
         ->asteroid('a2')
            ->prepend('#myDive2', '_p2', function(){ return array('var3'=>'Im Here!', 'var4'=>'You know it!'); })
    ->orbit();
 
    $this->render('test');
}

Example 2: Dynamically Rendering An Yii Grid View

When your partial contains a widget like CGridView that registers scripts and or style sheets to POS_HEAD you should use this approach.

public function actionTestUI()
{
    $this->asteroid('a1')
            ->renderMethod('render')
            ->replace('#myDiv3', '_p3GridView',  function() { 
                $sample = new Sample(); 
                if(isset($_GET['Sample'])) $sample->attributes = $_GET['Sample']; 
                return array('model' => $sample); 
              })
    ->orbit();
 
    $this->render('test');
}

Exmaple 3: Using onEvent()

Lets say we want to replace the content of div "#myDiv1" with the partial _p1.php when I click the div "#clickMe"

public function actionTestUI()
{
 
    $this->Asteroid('a3')->onEvent('click', '#clickMe') 
            ->replace('#myDiv1', '_p1', function() { return array('var1'=>'Yeah!', 'var2'=>'You clicked me…'); })
    ->orbit();
 
    $this->render('test');
}

Now lets say we want to execute some additional JavaScript on our click event.

public function actionTestUI()
{
    $this->Asteroid('a3')->onEvent('click', '#clickMe') 
            ->execJs("alert('I know you would click');")
            ->replace('#myDiv1', '_p1', function() { return array('var1'=>'Yeah!', 'var2'=>'You clicked me…'); })
    ->orbit();
 
    $this->render('test');
}

Exmaple 4: Using sendVars()

Lets say we would like to keep track of the number of clicks on a particular DOM element and update the view with the total. Every time a user clicks '#clickMe' we will replace the content of '#myDiv1' with the incremented count.

public function actionTestUI()
{
   $this->Asteroid('counterExample')
     ->onEvent('click', '#clickMe')
     ->sendVars(function($vars) {
        if(empty($vars)) $vars = array('count'=>0);
        $vars['count']++;
        return $vars;
     })
     ->replace('#myDiv1', '_myPlace3', function($vars) {
        return array('var1'=>'Cool I Clicked that', 'var2'=> . $vars['count'] . 'X');
     )}
   ->orbit();

Exmaple 5: Using useBelt()

The 'useBelt' method provides a way to keep things DRY, allowing you to aply groups of Asteroid actions you have defined.

To use 'useBelt' you will need to create at least one instance of EAsteroidBelt. Lets start there and create a folder in 'protected' called 'asteroidBelts' ('webapp/protected/asteroidBelts'). We will use this folder to store our Belts. Now we will create a new class called 'UiHelperAB' and save it to a file called 'UiHelperAB.php' in the 'asteroidBelts' directory we just created. Your class will look something like this:

class UiHelperAB extends EAsteroidBelt
{
 
    public function a1a2($myvar)
    {
        $this->Asteroid('a1')
            ->replace('#myDiv1', '_p1', function() use ($myvar) { return array('var1'=>'Yeah!', 'var2'=>$myvar); })
         ->Asteroid('a2')
            ->append('#myDive2', '_p2', function() { 
                 return array('var3'=>'Im Here!', 'var4'=>'You know it!'); 
            })
    }
 
    public function grid()
    {
        $this->Asteroid('grid')
            ->renderMethod('render')
            ->replace('#myDiv3', '_p3GridView',  function() { 
                $sample = new Sample(); 
                if(isset($_GET['Sample'])) $sample->attributes = $_GET['Sample']; 
                return array('model' => $sample); 
            })
    }
 
}

Cool we have an Asteroid Belt, now lets use it in our controller. Lets say we want to use a1a2:

public function actionTestUI()
{
    $myvar = "I did this with an Asteroid Belt!";
    $this->Asteroid('UIHelper')->useBelt(
        'application.asteroidBelts.UiHelperAB', 'a1a2', array($myvar)
    )
    ->Asteroid('someID')->...
    ->orbit();      
    ...
}

Great, but what if we want to use 'a1a2' and 'grid' in our controller action. We could just repeat the above line again and swap out the method name but there is another way. Lets take a look:

public function actionTestUI()
{
    $myvar = "I did this with an Asteroid Belt!";
    $this->Asteroid('UIHelper')->useBelt(
        'application.asteroidBelts.UiHelperAB', 
        array(
            array('a1a2', array($myvar)),
            array('grid', array()),
        )
    )
    ->Asteroid('someID')->...
    ->orbit();  
    ...
}

API

Public Methods

Method Description
Asteroid Initilizes Asteroid for the $id passed. $id should be unique unless you intend to overwrite an existing Asteroid. Example: Asteroid('block1').
onEvent Sets a custom event listener. Example: onEvent('click', '#someDomID'); The default is 'load', 'body'.
renderMethod Sets the Yii render type for your Asteroid. renderPartial is the default. Generally you only need to use pass 'render' if you are using Yii widgets like Grid View.
append Tells JS to dynamically load the specified view and append it to the specified DOM element.
prepend Same as append but prepends to DOM element content.
replace Same as append but replaces DOM element content.
execJS Call this method to add arbitrary JavaScript. Takes String $js of valid JavaScript. execJS('alert("Yeah!");')
sendVars Attach variables to your request.
useBelt Attach groups of predefined Asteroid Actions
orbit Renders all JS and CSS dependencies. You must Call orbit() as the very last step after all comets have been initialized with

Resources

GitHub

WebPage

API DOCS

Total 9 comments

#16467 report it
XzAeRo at 2014/02/26 09:36am
"Call-time pass-by-reference has been removed" Error

First, thank you for this awesome extension! It's exactly what I needed!

Now, when I first installed your extension I got the following error:

PHP Fatal Error: Call-time pass-by-reference has been removed in /Asteroid/behaviors/EAsteroid.php on line 75

The error is caused because since PHP version 5.4 pass-by-references have been removed. So changing this...

call_user_func_array(array(new $belt_class(&$this), $method[0]), $method[1]);

...to this...

call_user_func_array(array(new $belt_class($this), $method[0]), $method[1]);

...solved the problem!

#12186 report it
evan108108 at 2013/03/04 09:15pm
@bishoo @luc

First of all thank you Luc for finding that typo (it's now corrected).

Bishoo, Asteroid does not specially reference "dataProvider", however in the grid example (view: p3GridView.php) "dataProvider" is of course used to show the grid. Is it possible you are using this view instead of _p1?

#12182 report it
beesho at 2013/03/04 04:11pm
@luc

Thank you luc! I actually have a probelm when i add this line:

$this->asteroid('a1')
            ->replace('#myDiv1', '_p1', function(){ return array('var1'=>'Yeah!', 'var2'=>'Thats right!'); })
    ->orbit();

it throws "The "dataProvider" property cannot be empty. "

Any clue about that?

#12175 report it
luc at 2013/03/04 10:23am
@bishoo

Just follow the "usage" tutorial above. There's only a small typo error:

$this->render('test');

must be replaced with:

$this->render('index');

you can also rename view/sample/index.php to view/sample/test.php and keep $this->render('test') it is as you like !

you can then acces to http://your-Yii-app/sample/testUI

#12174 report it
beesho at 2013/03/04 09:13am
Demo?

Hello, It seems to be a nice extension.. Although i couldn't get it to work... Can you please provide a downloadable demo? Thanks

#11196 report it
luc at 2012/12/25 10:56am
Thank you for your help and your nice extension.

I did not set 'id' property of CGridView, so the ajax GET request werent sent by the gridview filters, however, sort was working well. Now, with the 'id' set, everything is OKay. BTW, it works also with bootstrap TbGridview.

I've got plans for using your extension in an application.

Merry Christmas

#11192 report it
evan108108 at 2012/12/24 04:57pm
RE: Works well: Working with GridView

Hi Luc,

Asteroid should play nicely with GridView if you do the following:

  1. You need to set the renderMethod = 'render' or a custom method that you define in your controller. This is because you need to capture the registered scripts.

  2. You need to capture the $_GET and set the model attributes.

Example (see above):

 $this->asteroid('a1')

        ->renderMethod('render')

        ->replace('#myDiv3', '_p3GridView',  function() { 

            $sample = new Sample(); 

            if(isset($_GET['Sample'])) $sample->attributes = $_GET['Sample'];

            return array('model' => $sample); 

          })

->orbit();
#11183 report it
luc at 2012/12/24 05:05am
Works well

Good for displaying "static" widgets, but with GridVIew the search GET request isn't sent when trying to filter the data grid.

#10890 report it
luc at 2012/11/29 03:09pm
looks good

In fact, exactly what I've done but in a more durtyer way ... I will have a look at it.

Leave a comment

Please to leave your comment.

Create extension