0

It there any way to create a "placeholder" inside the main view file for rendering other view files with specified data using Yii?

I want to individually process data in the controller then place them to a specified location in the view file before rendering.

Here is a widget example:

The widget class:

     class MyWidget extends CWidget
        {
            public $someData;
            public $mainData;

            public function init()
            {
            }

            public function run()
            {

              $this->render('mainView',array('data'=>$someData));

              foreach($data as $dat)
              {
                if(dat["color"]=="red")
                {
                    $display = 4;
                }
                else if(dat["color"]=="blue")
                {
                    $display = 6;
                }
                etc....
                //this is the fictional method for that purpose
                $this->addToPage('mainView','subView','placeholderName',
array('display'=>$display,'mainData'=>$main));
              }
            }
        }

The mainView file:

echo("<div class='someDesign'>");
echo($data);

$this->placeholder('placeholderName');

echo("</div>");

The subView file:

if($display>0 && $display<=4)    
  echo("<div class='dataColorG'>");
else if($display>0 && $display<=4)  
  echo("<div class='dataColorD'>");

echo $mainData;
echo("</div'>");

The solution based on Nikola's answer:

The widget class:

      class MyWidget extends CWidget
      {
        public $someData;
        public $mainData;

        public function init()
        {                    
        }

        public function run()
        {
           $output ="";
           foreach($data as $dat)
           {
              if(dat["color"]=="red")
              {
                 $display = 4;
              }
              else if(dat["color"]=="blue")
              {
                 $display = 6;
              }
              //If it's a widget we need to use $this->controller->renderPartial() instead of $this->renderPartial()
              $output.= $this->controller->renderPartial('subView',array('display'=>$display,'mainData'=>$main),true);
           }
           $this->render('mainView',array('subView'=>$output,'data'=>$someData));
         }
       }

The mainView file:

echo("<div class='someDesign'>");
echo($data);
echo($subView); //the 'placeholder'
echo("</div'>");

The subView file:

if($display>0 && $display<=4)    
    echo("<div class='dataColorG'>");
else if($display>0 && $display<=4)  
    echo("<div class='dataColorD'>");

echo $mainData;
echo("</div'>");
Crabman
  • 73
  • 6

2 Answers2

1

You can use renderPartial for this purpose. You can place the code for renderPartial isntead $this->placeholder('placeholderName'); e.g.:

$this->renderPartial('placeholderView', array($data));

Chech the other params - you can save to string or process js/css from the partials.

Nikola
  • 493
  • 4
  • 12
  • Is it possible to call renderPartial() from the controller? – Crabman Apr 21 '14 at 16:41
  • Yes it is :) . You can call renderPartial from controller or from the view itself. If you call it from controller you'd better save the response in a variable with the 3rd param set to true and then pass it to the view. I personally use it directly in the view where I want to render this partial view. – Nikola Apr 22 '14 at 08:39
0

You said "previously rendered file" which I interpret that you have the main file already in view in the browser, and then you would like to have new data processed by the controller and passed back the view, for which you would need an ajax call from the main view file somehow (maybe through an ajax button). If so have a look at CHtml::ajaxButton.

This allows you to call a controller action and push the resulting view to a DOM placeholder (using the HTML id). The replace key in ajaxOptions of CHtml::ajaxButton would replace the contents of the DOM placeholder. e.g.

'replace' => '#placeholder_id'

Edit

replace will actually replace the whole DOM element. If you want to replace the html content inside the DOM element you can use update key in ajaxOptions

<div id="subviewPlaceholder_id">html content</div>

Here is an example, which resides inside a form. The button push will send form data as get params. Use your controller action to read the params and $this->renderPartial('subView',array(... params ...)) to send back your sub view:

<?php
     echo '<div id="subviewPlaceholder_id"></div>';

     echo CHtml::ajaxButton('Get Sub View Button Name',array(
           'controller/getSubView','param1'=>$presetParam),
           array( // this is the ajaxOptions
               'type'=>'GET',
               'update'=>'#subviewPlaceholder_id', // id of DOM element for subview
           ), array( // this is the htmlOptions
               'class'=>'normalButton',
           ));
?>

Added

If you would like to place a sub view inside another view at initial render. Use @Nikola's suggestion

$this->renderPartial('subView',array(...params...));

Example main view file (followed by subview file). Place both files in your view folder:

<?php // mainView.php
     echo '<h1>MAIN VIEW</h1>';
     echo '<div class="class">'.$mainData->attribute1.'</div>'; 
     echo '<div class="class">'.$mainData->attribute2.'</div>';
     // render anything else

     // parameters for subView (processing should be done in controller actually)
     $display = $condition==$criteria?1:2;

     //this is where subview.php would be placed
     //You could get '_subView' from a variable and switch your subView according
     //to your criteria.
     $this->renderPartial('_subView', array(
             'display'=>$display,
             'param2'=>$param2));


     echo '<div>MAIN VIEW CONTINUED</div>'; // add any other rendering for main view
?>

And here is your sub view (prefix "_" for partial views by convention)

<?php // _subView.php
    if($display>0 && $display<=4)    
        echo("<div class='dataColorG'>");
    else if($display>0 && $display<=4)  
        echo("<div class='dataColorD'>");

    echo $param2; // add anything else to be rendered.

    echo "</div>";        
?>
nazim
  • 1,439
  • 2
  • 16
  • 26
  • Thanks for helping. Yes, I said "previously rendered file", but that is also okay if the controller load the main view, add the handles data to the placeholder (using the sub view file) then render the result to the browser. Is it possible too? – Crabman Apr 21 '14 at 16:40
  • Yes. Check addition to answer! – nazim Apr 21 '14 at 19:29
  • Thanks again! One more question: in the sample I used foreach to process mass data and add each of them to the main view using the _subview, and I'm wondering I need to put the foreach to the mainView with the processing ifs or is it possible somehow to call the renderPartial from the controller's foreach, because I want to keep the views simple, and design oriented and I want to handle that kind of processing in the controller. – Crabman Apr 21 '14 at 20:23
  • do the processing in your controller and pass the resulting $display to the mainview. The main view can pass the $display variable to the _subview - ps. please mark the answer correct if it worked for you! Thanks. – nazim Apr 21 '14 at 20:26