# Building a Good UI Framework with XHP

DevFeed: [Building a Good UI Framework with XHP](<https://devfeed.tech/articles/building-a-good-ui-framework-with-xhp-22036.md>)

Original publisher: [Read original article](<https://codebeforethehorse.tumblr.com/post/52824249342>)

Author: Codebeforethehorse

Published: 2013-06-12T23:23:00Z

Content type: tutorial

Language: en

Sources: [Stefan Parker](<https://devfeed.tech/sources/stefan-parker.md>)

Topics: [ui](<https://devfeed.tech/topics/ui.md>), [Framework](<https://devfeed.tech/topics/framework.md>)

Tags: [building](<https://devfeed.tech/tags/building.md>), [component](<https://devfeed.tech/tags/component.md>), [framework](<https://devfeed.tech/tags/framework.md>), [patterns](<https://devfeed.tech/tags/patterns.md>), [ui](<https://devfeed.tech/tags/ui.md>), [ui-framework](<https://devfeed.tech/tags/ui-framework.md>), [xhp](<https://devfeed.tech/tags/xhp.md>)

## AI overview

The article explains how Facebook built a UI framework on XHP, focusing on attribute forwarding and composition. It describes forwarding valid attributes from custom components to their rendered nodes and recommends composing components instead of extending them further.

## Source excerpt

This is the article I wanted to write ever since I started this blog. XHP is a really powerful tool, but like any tool you need to know how to use it for it to be really effective. Facebook has built a very powerful UI framework on top of XHP, but we had to change the way we think about object patterns to do it. I'll get into that in a bit, but first I'm going to jump right into the most important feature of Facebook's UI library: attribute forwarding. Here's the problem, when you make your own XHP component, the element you return in your render method is exactly what will be sent down the wire. That means if you want to apply IDs, classes, onclicks, or any other attributes to an individual instance, you'll have to account for that in your class and set it on the returned node. Here's what I mean by that. class :ui:div extends :x:element { attribute :div; protected function render() { $root = <div />; $root->setAttributes(array( 'id' => $this->getAttribute('id'), 'class' => $this->getAttribute('class'), ... ); return $root; } } That's not a good pattern, so a good UI framework should do this for you. At Facebook, we call our UI core element :ui:base, and this is how we forward attributes: First, we set :ui:base::render() to be final and instead create an abstract method compose() that all extensions will need to override. Then we can get the attributes set on the instance being rendered and compare it with the attribute declaration on the returned node from compose(). We loop through the set attributes and forward them onto returned node (if valid). So our class ends up looking something like this: abstract class :ui:base extends :x:element { abstract protected function compose(); final public function addClass($class) { $this->setAttribute( 'class', trim($this->getAttribute('class').' '.$class) ); return $this; } final protected function render() { $root = $this->compose(); if ($root === null) { return <x:frag />; } if (:x:base::$ENABLE_VALIDATION) { if (!$root in