-
-
Notifications
You must be signed in to change notification settings - Fork 5
DOM manipulation
WebEngine renders HTML by working with a real document model on the server. That means the page can be manipulated using familiar DOM ideas rather than only through string concatenation.
The DOM package itself is documented in more detail at https://www.php.gt/docs/Dom/.
Direct DOM manipulation is useful when you need to change the structure of the document, move nodes around, or work with a one-off element relationship.
Example of direct DOM manipulation:
use GT\Dom\HTMLDocument;
use Gt\Http\Uri;
function go(HTMLDocument $document, Uri $uri):void {
// Mark the link's parent that matches the current URI in as "selected":
foreach($document->querySelectorAll("main-menu a") as $link) {
if($link->href === $uri->getPath()) {
$link->parentElement->classList->add("selected");
}
}
}Binding is usually cleaner when the structure is already present in HTML and you only need to fill in values. The two approaches work well together, but binding should usually be the default because it keeps the page view and the PHP more loosely coupled.
Example of binding:
use GT\DomTemplate\Binder;
use GT\Database\Database;
function go(Binder $binder, Database $db):void {
$row = $db->fetch("currentEntity");
$binder->bindData($row);
}In the above two examples, notice how when using the Binder, the PHP code doesn't necessarily need to know anything about the page structure, whereas when using the HTMLDocument directly, the PHP is more tightly coupled to the structure of the HTML.
When using HTMLDocument in WebEngine, the most common operations fall into four groups:
- finding the elements we need
- changing text, attributes, or classes
- creating or moving nodes
- inspecting relationships such as parents, children, and nearest matches
The API is intentionally close to the browser DOM, so methods such as querySelector(), querySelectorAll(), closest(), createElement(), appendChild(), before(), after(), and replaceWith() work in familiar ways.
Selector-based traversal is usually the starting point:
use GT\Dom\HTMLDocument;
function go(HTMLDocument $document):void {
$title = $document->querySelector("main h1");
$buttons = $document->querySelectorAll("form[action] button");
$title?->classList->add("is-ready");
foreach($buttons as $button) {
$button->disabled = false;
}
}querySelector() returns the first matching element or null. querySelectorAll() returns a NodeList of all matches. In PHP.GT/Dom, that list is static, so if you later add matching elements, the original list does not update itself.
Read more in the main DOM docs: https://www.php.gt/docs/Dom/Document-traversal/
Once we have the right element, the next step is usually to adjust content or element state.
use GT\Dom\HTMLDocument;
function go(HTMLDocument $document):void {
$document->querySelector(".customer-name")->innerText = "Cody";
$document->querySelector(".customer-email")->textContent = "cody@example.com";
$profileLink = $document->querySelector("a.profile-link");
$profileLink->href = "/user/cody";
$profileLink->setAttribute("data-user-id", "42");
$status = $document->querySelector(".status");
$status->classList->remove("is-offline");
$status->classList->add("is-online");
}innerText is usually the most natural choice for visible text in HTML. Properties such as href, src, value, hidden, title, and tabIndex can also be manipulated directly, and classList gives a clean interface for adding, removing, replacing, and toggling classes.
Read more in the main DOM docs: https://www.php.gt/docs/Dom/Working-with-HTML-specific-helpers/
Direct DOM work becomes especially useful when the page structure itself has to change.
use GT\Dom\HTMLDocument;
function go(HTMLDocument $document):void {
$list = $document->createElement("ul");
foreach(["Draft", "Review", "Published"] as $label) {
$item = $document->createElement("li");
$item->innerText = $label;
$list->appendChild($item);
}
$panel = $document->querySelector("#status-panel");
$panel?->appendChild($list);
}The same approach works for adding banners, wrapping existing content, inserting separators, or replacing one structure with another. Because the page is a real document tree, those structural changes stay explicit and local.
DOM work is not only about selectors from the root document. Often the useful move is relative navigation from an element we already have:
use GT\Dom\HTMLDocument;
function go(HTMLDocument $document):void {
$error = $document->querySelector(".field-error");
$group = $error?->closest(".form-group");
$group?->classList->add("has-error");
$notice = $document->querySelector(".notice");
$notice?->before($document->createElement("hr"));
}Properties such as parentElement, children, nextElementSibling, and methods such as closest() make it possible to express document-local logic without repeatedly searching the whole page.
Prefer binding for routine content output where the HTML structure already exists and only the values change. Reach for direct DOM manipulation when:
- the page structure must be inserted, removed, or rearranged
- one element's state depends on another element's location or relationship
- repeated binding keys would be more awkward than just editing the relevant nodes directly
- the behaviour is naturally expressed as document operations rather than data mapping
If the PHP keeps reaching deep into many unrelated parts of the page, that is usually a sign the view structure should be improved, or that some of the work should move back into binding data to the DOM, custom HTML components, or page partials.
For deeper DOM coverage, the best entry points in the main docs are:
- https://www.php.gt/docs/Dom/Home/
- https://www.php.gt/docs/Dom/Document-traversal/
- https://www.php.gt/docs/Dom/Working-with-HTML-specific-helpers/
- https://www.php.gt/docs/Dom/WebEngine-and-DomTemplate/
See how binding data to the DOM can keep dynamic pages clean and maintainable, or move on to work with user input.
- File-based routing
- Page views
- Page logic
- Dynamic URIs
- Headers and footers
- Custom HTML components
- Page partials
- Binding data to the DOM
- DOM manipulation
- Hello You tutorial
- Todo list tutorial
- Address book tutorial WIP
- Blueprints
- Application architecture
- Coding styleguide WIP
- PHP environment setup WIP
- Web servers WIP
- Background cron tasks
- Database setup WIP
- Client-side compilation WIP
- Testing WebEngine applications WIP
- Production checklist WIP
- Security WIP