# **Chapter 5: FrontFile Events - Interacting with Templates** > **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` --- ## **5.1 What are FrontFile Events?** FrontFile Events allow your Gate class to interact with the FrontFile template. While Page Events handle browser requests, FrontFile Events handle template interactions. These events are called at specific times during FrontFile processing, allowing you to: - Modify Components before/after they're created - Set metadata dynamically - Handle Component-specific events - Inject dynamic content ## **5.2 The FrontFile Event Methods** ### **onfrontinit($frontobj) - FrontFile Just Loaded** Called immediately after the FrontFile is loaded but before Components are created. ```php public function onfrontinit($frontobj) { // $frontobj is the FrontFile instance // Set page metadata $frontobj->addMetaData("title", "My Product Page"); $frontobj->addMetaData("description", "Products available for purchase"); $frontobj->addMetaData("keywords", "products,shop,online"); } ``` ### **onfrontprocess($frontobj) - FrontFile Processed** Called after the FrontFile has been fully processed - all Components created, all Fusion attributes executed. ```php public function onfrontprocess($frontobj) { // At this point, all Components exist // We can modify Components before rendering $txtTitle = $frontobj->getComponent("txtTitle"); $txtTitle->fu_setReadonly(true); // Make it read-only // Or hide/show components based on logic $divAdmin = $frontobj->getComponent("divAdmin"); if (!$this->page->isAuthenticate("ADMIN")) { $divAdmin->unsetVisible(); } } ``` ## **5.3 Interacting with Components** ### **Getting Components** ```php // Get a specific component by ID $textField = $this->frtMain->getComponent("txtName"); $dropdown = $this->frtMain->getComponent("sltCategory"); $div = $this->frtMain->getComponent("divContent"); ``` ### **Modifying Components** ```php public function page_new() { // Get component $txtName = $this->frtMain->getComponent("txtName"); // Set value (Render Phase) $txtName->fu_setValue("John Doe"); // Set default value (Parse Phase) $txtName->fi_setDefaultValue("Enter your name"); // Make read-only $txtName->fu_setReadonly(true); // Hide component $txtName->unsetVisible(); // Show component $txtName->setVisible(); // Set inner HTML $divContent = $this->frtMain->getComponent("divContent"); $divContent->setInnerHTML("<p>Dynamic content here</p>"); } ``` ### **Working with Forms** For database operations with forms, use `$this->page` helper methods (see Section 5.8 for details): ```php public function page_submit() { // Get form component $form = $this->frtMain->getComponent("userForm"); // Get record ID $currentId = $form->getRecID(); // Check if form is in insert or update mode if ($currentId == "") { // New record mode - use $this->page->insertData() $insertedID = $this->page->insertData($form); } else { // Edit mode - use $this->page->updateData() $this->page->updateData($form, array(), $currentId); } } // View record for editing public function page_event_edit($evtp) { $form = $this->frtMain->getComponent("userForm"); $this->page->viewData($form, $evtp); } // Delete record public function page_delete() { $this->page->deleteRec(); } ``` ## **5.4 Component Events from FrontFile** You can also handle events that originate from Components in your FrontFile using the naming pattern: ### **Component Event Naming** In your FrontFile, add attributes like `on-init="true"` or `on-create="true"`: ```html <input id="txtName" runat="server" on-init="true" on-create="true"> ``` Then in your Gate, create methods following this pattern: ```php public function comp_txtName_on_init($evtp) { // Called when txtName Component initializes // $evtp contains: ['obj' => component, 'element' => NodeTag, 'value' => value] $component = $evtp['obj']; $component->fi_setDefaultValue("Guest User"); } public function comp_txtName_on_create($evtp) { // Called after txtName Component is fully created $component = $evtp['obj']; // Additional setup } ``` ### **Handling Multiple Component Events** ```php // In FrontFile: // <input id="txtEmail" runat="server" on-init="true"> public function comp_txtEmail_on_init($evtp) { $component = $evtp['obj']; // Add validation $component->fi_setEmail(); $component->fi_setRequired(); } ``` ## **5.5 Using Holder in FrontFile** The `runas="holder"` attribute creates placeholders for dynamic content: ### **Holder Patterns in FrontFile** ```html <!-- Div Tag pass to Component onholder event --> <div runas="holder" sphp-comp="sltcategory"></div> <!-- Div Tag pass to Gate onholder event --> <div runas="holder"></div> <!-- Get content from Gate property --> <div runas="holder" sphp-app-prop="pageTitle"></div> <!-- Get content from Component property --> <div runas="holder" sphp-comp="myComponent" sphp-comp-prop="output"></div> <!-- Get return from Component method --> <div runas="holder" sphp-comp="pagination" sphp-comp-fun="getPageLinks"></div> <!-- Get from Gate method --> <div runas="holder" sphp-app-fun="getUserList"></div> ``` ### **Setting Holder Content in Gate** ```php public function page_new() { // Set property for holder $this->frtMain->addProp("pageTitle", "Welcome to My Site"); // Or set directly on FrontFile $this->frtMain->addProp("userList", $this->getUserListHTML()); $this->setFrontFile($this->frtMain); } // Method that returns HTML for holder public function getUserListHTML() { $users = $this->dbEngine->executeQueryQuick("SELECT * FROM users"); $html = "<ul>"; foreach ($users as $user) { $html .= "<li>{$user['name']}</li>"; } $html .= "</ul>"; return $html; } ``` ## **5.6 The onholder Event** There's also a special `onholder` method that gets called for any holder tag: ```php public function onholder($element) { // $element is the NodeTag with runas="holder" // Check what kind of holder it is $type = $element->getAttribute("data-type"); switch ($type) { case "user-list": $html = $this->getUserListHTML(); $element->setInnerHTML($html); break; case "product-grid": $html = $this->getProductGridHTML(); $element->setInnerHTML($html); break; case "recent-posts": $html = $this->getRecentPostsHTML(); $element->setInnerHTML($html); break; } } ``` FrontFile: ```html <div runas="holder" data-type="user-list"></div> <div runas="holder" data-type="product-grid"></div> <div runas="holder" data-type="recent-posts"></div> ``` ## **5.7 Complete Example - Product Catalog** Here's a Gate demonstrating FrontFile Events: ```php <?php // apps/Product.gate.php use Sphp\tools\BasicGate; class Product extends BasicGate { private $frtList; private $frtEdit; public function onstart() { $this->getAuthenticate("GUEST,MEMBER,ADMIN"); // Set default table name for $this->page database methods $this->page->tblName = "products"; $this->frtList = new \Sphp\tools\FrontFile($this->mypath . "/fronts/product_list.front"); $this->frtEdit = new \Sphp\tools\FrontFile($this->mypath . "/fronts/product_edit.front"); } /** * FrontFile Event: onfrontinit * Set metadata for list page */ public function onfrontinit($frontobj) { // Determine which FrontFile if ($frontobj === $this->frtList) { $frontobj->addMetaData("title", "Product Catalog"); $frontobj->addMetaData("description", "Browse our products"); } else { $frontobj->addMetaData("title", "Product Form"); } } /** * FrontFile Event: onfrontprocess * Modify components after processing */ public function onfrontprocess($frontobj) { // Hide admin-only elements from non-admins if (!$this->page->isAuthenticate("ADMIN")) { $deleteBtn = $frontobj->getComponent("btnDelete"); if ($deleteBtn) { $deleteBtn->unsetVisible(); } } } /** * Lifecycle Event: onready * Prepare components */ public function onready() { // Pre-populate category dropdown $sltCategory = $this->frtEdit->getComponent("sltCategory"); $categories = $this->getCategories(); $sltCategory->setOptions($categories); // Set default values $txtDate = $this->frtEdit->getComponent("txtDate"); $txtDate->fi_setDefaultValue(date("Y-m-d")); } /** * Page Event: page_new - Show product list * Method 1: Using $this->dbEngine directly (verbose but flexible) */ public function page_new() { $this->dbEngine->connect(); $result = $this->dbEngine->executeQuery("SELECT * FROM products ORDER BY name"); // Build HTML for list $html = ""; while ($product = $this->dbEngine->row_fetch_assoc($result)) { $html .= "<div class='product'>"; $html .= "<h3>{$product['name']}</h3>"; $html .= "<p>Price: \${$product['price']}</p>"; $html .= "<a href='product-view-{$product['id']}.html'>View</a>"; $html .= "</div>"; } $this->dbEngine->disconnect(); // Inject into FrontFile $this->frtList->getComponent("divProducts")->setInnerHTML($html); $this->setFrontFile($this->frtList); } /** * Alternative: Using $this->page helper methods for database operations * These methods reduce code when Components use Database Binding (dfield and dtable attributes) */ /** * View data - Fill form components from database record * Usage: Components need dfield and dtable attributes */ public function page_event_view($evtp) { // $evtp contains the record ID $form = $this->frtEdit->getComponent("productForm"); // Fill form with data from database $this->page->viewData($form, $evtp); $this->setFrontFile($this->frtEdit); } /** * Insert data - Save form components to database * Components need dfield and dtable attributes */ public function page_insert() { $form = $this->frtEdit->getComponent("productForm"); // Extra fields to insert $extra = array(); $extra[]['created_at'] = date('Y-m-d H:i:s'); // Insert data - returns new record ID $insertedID = $this->page->insertData($form, $extra); echo "New product inserted with ID: " . $insertedID; } /** * Update data - Update existing database record * Components need dfield and dtable attributes */ public function page_update() { $form = $this->frtEdit->getComponent("productForm"); $recID = $form->getRecID(); // Get record ID from form // Extra fields to update $extra = array(); $extra[]['updated_at'] = date('Y-m-d H:i:s'); // Update data $this->page->updateData($form, $extra, $recID); echo "Product updated!"; } /** * Delete data - Delete database record */ public function page_delete() { // Delete record using event parameter as record ID $this->page->deleteRec(); echo "Product deleted!"; } /** * Component Event Handler * When txtName gets initialized */ public function comp_txtName_on_init($evtp) { $component = $evtp['obj']; $component->fi_setRequired(); $component->fi_setMinLen(3); } /** * Custom method for holder */ public function getFeaturedProducts() { // auto connect to db if not connected $result = $this->dbEngine->executeQueryQuick( "SELECT * FROM products WHERE featured = 1 LIMIT 5" ); $html = "<div class='featured'>"; while ($p = $this->dbEngine->row_fetch_assoc($result)) { $html .= "<div class='item'>{$p['name']} - \${$p['price']}</div>"; } $html .= "</div>"; return $html; } private function getCategories() { return "Electronics,Clothing,Books,Home,Garden"; } } ``` ## **5.8 $this->page Helper Methods for Database Operations** SartajPHP provides helper methods through `$this->page` object that reduce code when working with database operations. These methods work with Components that have database binding attributes (`dfield` and `dtable`). ### **Setting Table Name** Before using database methods, set the default table name: ```php public function onstart() { $this->page->tblName = "products"; } ``` ### **$this->page->viewData($form, $recID, $fldList, $where)** Fill form components with data from database: ```php public function page_event_edit($evtp) { $form = $this->frtEdit->getComponent("productForm"); // Fill form with record data // $evtp is the record ID $this->page->viewData($form, $evtp); // Or specify custom fields and where clause // $this->page->viewData($form, '', "name,price,description", "WHERE id=5"); $this->setFrontFile($this->frtEdit); } ``` ### **$this->page->insertData($form, $extra)** Insert form component values to database: ```php public function page_insert() { $form = $this->frtEdit->getComponent("productForm"); // Extra fields to insert $extra = array(); $extra[]['created_at'] = date('Y-m-d H:i:s'); $extra[]['created_by'] = $this->page->getUserID(); $insertedID = $this->page->insertData($form, $extra); // Returns new record ID echo "Inserted record ID: " . $insertedID; } ``` ### **$this->page->updateData($form, $extra, $recID, $where)** Update existing database record: ```php public function page_update() { $form = $this->frtEdit->getComponent("productForm"); $recID = $form->getRecID(); // Get from form component // Extra fields to update $extra = array(); $extra[]['updated_at'] = date('Y-m-d H:i:s'); // Update record $this->page->updateData($form, $extra, $recID); // Or use custom where clause // $this->page->updateData($form, $extra, '', "WHERE code='ABC'"); } ``` ### **$this->page->deleteRec($recID)** Delete a database record: ```php public function page_delete() { // Delete using event parameter as record ID $this->page->deleteRec(); // Or specify record ID explicitly // $this->page->deleteRec(5); } ``` ### **Database Binding in FrontFile Components** For `$this->page` helper methods to work, Components need database binding attributes: ```html <form id="productForm" runat="server"> <input id="txtName" runat="server" dfield="name" dtable="products" /> <input id="txtPrice" runat="server" dfield="price" dtable="products" type="number" /> <textarea id="txtDesc" runat="server" dfield="description" dtable="products"></textarea> </form> ``` - `dfield`: Database table field name - `dtable`: Database table name (optional if $this->page->tblName is set in onstart) ## **5.9 Chapter Summary** 1. **FrontFile Events** allow Gate-template interaction 2. **onfrontinit($frontobj)** - Called after FrontFile loaded 3. **onfrontprocess($frontobj)** - Called after FrontFile processed 4. **onready()** - Components are accessible, modify them here 5. **Component Events** - Handle via `comp_componentId_on_event()` 6. **Holders** - Use `runas="holder"` with `sphp-app-prop`, `sphp-comp`, or `sphp-app-fun` 7. **$this->page helper methods** - Use `viewData`, `insertData`, `updateData`, `deleteRec` for database operations ## **5.10 What's Next?** Now you understand how Gate interacts with FrontFile. Next, let's build actual webpages using Front Files and Master Files. --- *Next: Chapter 6 - Building Your First Webpage*