# **Chapter 9: The runas="holder" Attribute - Dynamic Content Injection**
> **File Extension Reference:**
> - Gate Files: `*.gate.php` (e.g., `Index.gate.php`)
> - Front Files: `*.front` (e.g., `index_main.front`)
> - Master Files: `*.mast.php` (e.g., `default/master.mast.php`)
> - Front Places: `*.place.front` or `*.place.php`
---
## **9.1 What is runas="holder"?**
The `runas="holder"` attribute creates a **placeholder** in your FrontFile that gets filled with dynamic content from your Gate class. It's like a slot that gets populated at render time.
Unlike `runat="server"` which creates a Component, `runas="holder"` just marks a spot for dynamic content without creating a Component.
## **9.2 Basic Holder Syntax**
```html
<div runas="holder" sphp-app-prop="contentName"></div>
```
- `runas="holder"` - Marks this as a placeholder
- `sphp-app-prop` - Property name to get from FrontFile
## **9.3 Setting Holder Content from Gate**
### **Method 1: Using addProp()**
```php
public function page_new()
{
// Add property to FrontFile
$this->frtMain->addProp("welcomeMessage", "Hello, World!");
// Set the holder content
$this->setFrontFile($this->frtMain);
}
```
In FrontFile:
```html
<div runas="holder" sphp-app-prop="welcomeMessage"></div>
```
Output: `<div>Hello, World!</div>`
### **Method 2: Direct Property on Gate**
```php
// In Gate
public function page_new()
{
$this->siteName = "My Website";
$this->userCount = 150;
$this->setFrontFile($this->frtMain);
}
```
In FrontFile:
```html
<h1>##{$parentgate->siteName}#</h1>
<p>Users: ##{$parentgate->userCount}#</p>
<div runas="holder" sphp-app-prop="siteName"></div>
```
## **9.4 Holder from Component**
Get content from a Component property:
```html
<!-- Get from a Component -->
<div runas="holder" sphp-comp="myComponent" sphp-comp-prop="output"></div>
```
In Gate, the Component would have:
```php
// Component returns HTML
public function getOutput()
{
return "<p>Component content</p>";
}
```
## **9.5 Holder from Component Method (Function)**
Call a Component method directly:
```html
<!-- Call getPageLinks() method on pagination Component -->
<div runas="holder" sphp-comp="pagination" sphp-comp-fun="getPageLinks"></div>
```
## **9.6 Holder from Gate Method (Function)**
Call a Gate method directly:
```html
<!-- Call getUserList() method on Gate -->
<div runas="holder" sphp-app-fun="getUserList"></div>
```
In Gate:
```php
public function getUserList()
{
$this->dbEngine->connect();
$result = $this->dbEngine->executeQuery("SELECT * FROM users LIMIT 10");
$html = "<ul>";
while ($user = $this->dbEngine->row_fetch_assoc($result)) {
$html .= "<li>{$user['name']}</li>";
}
$html .= "</ul>";
$this->dbEngine->disconnect();
return $html;
}
```
## **9.7 Practical Example - Dynamic Sidebar**
### Gate Code:
```php
<?php
// apps/Product.gate.php
use Sphp\tools\BasicGate;
class Product extends BasicGate
{
private $frtMain;
public function onstart()
{
$this->frtMain = new \Sphp\tools\FrontFile($this->mypath . "/fronts/product_page.front");
}
public function onready()
{
// Set properties for holders
$this->frtMain->addProp("categoryList", $this->getCategoryList());
$this->frtMain->addProp("featuredProducts", $this->getFeaturedProducts());
$this->frtMain->addProp("recentPosts", $this->getRecentPosts());
}
public function page_new()
{
$this->setFrontFile($this->frtMain);
}
private function getCategoryList()
{
$cats = ["Electronics", "Clothing", "Books", "Home", "Sports"];
$html = "<ul class='list-group'>";
foreach ($cats as $cat) {
$html .= "<li class='list-group-item'>$cat</li>";
}
$html .= "</ul>";
return $html;
}
private function getFeaturedProducts()
{
// In real app, fetch from database
$html = "<div class='card'>";
$html .= "<div class='card-body'><h5>Featured Product</h5>";
$html .= "<p>Special discount!</p></div>";
$html .= "</div>";
return $html;
}
private function getRecentPosts()
{
return "<p>Recent blog posts will appear here.</p>";
}
}
```
### FrontFile:
```html
<!-- product_page.front -->
<div class="row">
<!-- Main Content -->
<div class="col-md-9">
<h1>Products</h1>
<p>Welcome to our product catalog!</p>
<!-- Products would go here -->
</div>
<!-- Sidebar with Holders -->
<div class="col-md-3">
<div class="card mb-3">
<div class="card-header">Categories</div>
<div class="card-body">
<!-- Holder gets content from categoryList property -->
<div runas="holder" sphp-app-prop="categoryList"></div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">Featured</div>
<div class="card-body">
<div runas="holder" sphp-app-prop="featuredProducts"></div>
</div>
</div>
<div class="card">
<div class="card-header">Latest Posts</div>
<div class="card-body">
<div runas="holder" sphp-app-prop="recentPosts"></div>
</div>
</div>
</div>
</div>
```
## **9.8 Using Holder with onholder Event**
For more complex dynamic content, use the `onholder()` event in your Gate:
```php
// In Gate - catches any holder without specific sphp-app-prop
public function onholder($element)
{
$type = $element->getAttribute("data-widget-type");
switch ($type) {
case "user-stats":
$html = $this->getUserStats();
$element->setInnerHTML($html);
break;
case "product-grid":
$html = $this->getProductGrid();
$element->setInnerHTML($html);
break;
case "news-feed":
$html = $this->getNewsFeed();
$element->setInnerHTML($html);
break;
}
}
```
FrontFile:
```html
<div runas="holder" data-widget-type="user-stats"></div>
<div runas="holder" data-widget-type="product-grid"></div>
<div runas="holder" data-widget-type="news-feed"></div>
```
## **9.9 Holder vs Component**
| Aspect | runat="server" (Component) | runas="holder" |
|--------|---------------------------|----------------|
| Creates | Component object | No Component |
| Use Case | Interactive elements | Static content |
| Lifecycle | Has events (oninit, onrender, etc.) | No events |
| Database | Can use dtable/dfield | Just displays content |
| Best For | Forms, inputs, interactive | Sidebars, lists, static sections |
## **9.10 Holder with Conditional Logic**
Use expression tags for conditional holder content:
```html
<!-- Show different content based on login status -->
#{if $parentgate->isLoggedIn()}#
<div runas="holder" sphp-app-prop="loggedInSidebar"></div>
#{else}#
<div runas="holder" sphp-app-prop="guestSidebar"></div>
#{endif}#
```
Or conditional class based on holder content:
```html
<div class="alert ##{$hasError ? 'alert-danger' : 'alert-info'}#">
<div runas="holder" sphp-app-prop="statusMessage"></div>
</div>
```
## **9.11 Chapter Summary**
1. **runas="holder"** creates placeholder for dynamic content
2. **sphp-app-prop** - Get content from FrontFile property
3. **sphp-comp** - Get content from Component
4. **sphp-comp-fun** - Call Component method
5. **sphp-app-fun** - Call Gate method directly
6. **onholder()** event - Handle holders dynamically
7. Use holders for sidebars, lists, static content
8. Use Components (`runat="server"`) for interactive elements
## **9.12 What's Next?**
Next, learn about Code Blocks - how to enhance FrontFile design with reusable styling and layout transformations.
---
*Next: Chapter 10 - Code Blocks: Enhancing FrontFile Design*