# **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*