From d5a807c6b25e6d38c6c160076862bb84f0791b5c Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Thu, 5 Sep 2024 15:45:40 +0100 Subject: [PATCH] Update attributes.md --- handbook/attributes.md | 155 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 11 deletions(-) diff --git a/handbook/attributes.md b/handbook/attributes.md index f4e6637..86ed62f 100644 --- a/handbook/attributes.md +++ b/handbook/attributes.md @@ -1,24 +1,157 @@ # Attributes deep dive -You’ve just rebuilt 90% of Phlex so you know a thing or two about rendering attributes. +You’ve just rebuilt 90% of Phlex so you know a thing or two about rendering attributes, right? + +In the previous example, we rendered attributes like this: + +```ruby +attributes.each do |key, value| + @buffer << " #{key}=\"#{value}\"" +end +``` ## Keys -- Difference between string and symbol keys +If you use symbols for keys, Phlex will replace underscores `_` with dashes `-`. This is because the convention in HTML is to use dashes, while on the Ruby side, dashes are not allowed in symbols. + +If you need to keep an underscore in the attribute name, you can use a string instead: -## Values +::: code-group -- Strings -- Arrays -- Sets -- Booleans -- Custom objects +```ruby [component] +h1(data_controller: "hello") { "Hello!" } +h1("data_controller" => "hello") { "Hello!" } +``` + +```html [output] +

👋 Hello World!

+

👋 Hello World!

+``` + +::: ## Nested attributes -- Describe how hashes work +You can nest attributes by using a hash as the value. The hash will be flattened with a dash between each level: + +::: code-group + +```ruby [component] +h1(data: { controller: "hello" }) { "Hello!" } +``` + +```html [output] +

👋 Hello World!

+``` + +::: + +## Attribute values + +You’ve seen how string values work. Symbols behave the same way. You’ve also seen how to nest attributes with hashes. But Phlex allows a few other types of attribute value. + +### Arrays and sets + +::: code-group + +```ruby [component] +h1(class: ["foo", "bar"]) { "Hello!" } +h1(class: Set["foo", "bar"]) { "Hello!" } +``` + +```html [output] +

Hello!

+

Hello!

+``` + +::: + +### Booleans + +Booleans are a special case. If the value is `true`, Phlex will render the attribute without a value. If the value is `false`, Phlex will not render the attribute at all. + +::: code-group + +```ruby [component] +textarea(disabled: true) +textarea(disabled: false) +``` + +```html [output] + +``` + +::: + +::: tip +Some HTML attributes such as `contenteditable` require you to pass `"true"` or `"false"` as a string. These are not technically “boolean” attributes, they're “enumerated” attributes. The distinction is subtle but important. + +::: ## Special attributes -- `style` -- `class` +### `class` + +The `class` attribute is special. It behaves differently when you pass a Hash as a value, allowing you to conditionally add classes. Here, the class `active` is added because `is_active` is _truthy_, and the class `disabled` is not added because `is_disabled` is _falsy_: + +::: code-group + +```ruby [component] +is_active = true +is_disabled = false + +a(class: { active: is_active, disabled: is_disabled }) { "Click me" } +``` + +```html [output] +👋 Hello World! +``` + +::: + +You can also use this with an array: + +::: code-group + +```ruby{6} [component] +is_active = true +is_disabled = false + +a( + class: [ + "button", + "active" => is_active, + "disabled" => is_disabled + ] +) { "Click me" } +``` + +```html [output] +👋 Hello World! +``` + +In this example, the `button` class is always added, while the `active` and `disabled` classes are conditional. You can read `=>` as “if”. + +### `style` + +Like `class`, the `style` attribute has special behaviour. If you pass a Hash to `style`, Phlex will convert it to a CSS string: + +::: code-group + +```ruby [component] +h1(style: { color: "red", font_size: "16px" }) { "Hello!" } +``` + +```html [output] +

Hello!

+``` + +::: + +### `href` on an `` tag + +It’s worth noting here that Phlex will not allow you to set the `href` attribute to anything that begins with `javascript:`. This is a security feature to prevent cross-site-scripting (XSS) attacks. + +## Event attributes + +Event attributes such as `onclick` are disallowed to prevent cross-site-scripting (XSS) attacks.