Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .claude/skills/layered-ui-rails/references/HELPERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ Field options:
- `required` (Boolean, optional) - marks field as required; default false
- `hint` (String, optional) - help text below the field
- `collection` (Array, optional) - required for `:select` type; e.g. `[['Label', value], ...]`
- `include_blank` (Boolean or String, optional) - for `:select` fields; defaults to `true`. Pass a string to use as the blank option's label, or `false` to omit it. Suppressed when `prompt:` is set
- `prompt` (String, optional) - for `:select` fields; prompt text shown as the first option, only selectable when no value is set
- `placeholder` (String, optional) - input placeholder text

```erb
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to this project will be documented in this file. This project follows [Semantic Versioning](https://semver.org/).

## [Unreleased]

### Added

- `prompt:` field option on `:select` fields in `l_ui_form`, shown as the first option and only selectable when no value is set; suppresses the default blank option

## [0.16.1] - 2026-05-16

### Fixed
Expand Down
4 changes: 3 additions & 1 deletion app/helpers/layered/ui/form_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def l_ui_normalise_field(record, config)
label = config[:label] || attribute.to_s.humanize

extras = config.except(:attribute, :as, :label, :required, :hint,
:collection, :placeholder)
:collection, :placeholder, :prompt, :include_blank)

{
attribute: attribute,
Expand All @@ -45,6 +45,8 @@ def l_ui_normalise_field(record, config)
hint: config[:hint],
collection: config[:collection],
placeholder: config[:placeholder],
prompt: config[:prompt],
include_blank: config[:include_blank],
extras: extras
}
end
Expand Down
10 changes: 7 additions & 3 deletions app/views/layered/ui/managed_resource/_field_input.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@
<%
collection = config[:collection]
choices = collection.respond_to?(:call) ? collection.call : collection
include_blank = extras.delete(:include_blank)
include_blank = true if include_blank.nil?
include_blank = config[:include_blank]
prompt = config[:prompt]
include_blank = true if include_blank.nil? && prompt.nil?
select_options = {}
select_options[:include_blank] = include_blank unless include_blank.nil?
select_options[:prompt] = prompt unless prompt.nil?
%>
<div class="l-ui-select-container">
<%= form.select(attribute, choices, { include_blank: include_blank },
<%= form.select(attribute, choices, select_options,
class: field_class.call("l-ui-select"), **base_opts, **extras) %>
</div>
<% elsif config[:as] == :checkbox %>
Expand Down
12 changes: 12 additions & 0 deletions test/dummy/app/views/pages/forms_helper.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
{ attribute: :title, as: :string, required: true, placeholder: "Enter a title" },
{ attribute: :body, as: :text, hint: "A longer description" },
{ attribute: :user_id, as: :select, label: "Author",
prompt: "Choose an author",
collection: @users.map { |u| [u.name, u.id] } },
],
url: "#") %>
Expand All @@ -65,6 +66,7 @@
{ attribute: :body, as: :text,
hint: "A longer description" },
{ attribute: :user_id, as: :select, label: "Author",
prompt: "Choose an author",
collection: User.pluck(:name, :id) },
],
url: posts_path) %&gt;</code></pre>
Expand Down Expand Up @@ -162,6 +164,16 @@
<td class="l-ui-table__cell">Array / Proc</td>
<td class="l-ui-table__cell">Options for <code>:select</code> fields. Array of <code>[label, value]</code> pairs or a callable.</td>
</tr>
<tr>
<th class="l-ui-table__cell l-ui-table__cell--primary" scope="row"><code>prompt:</code></th>
<td class="l-ui-table__cell">String</td>
<td class="l-ui-table__cell">Prompt text for <code>:select</code> fields (e.g. "Choose an author"). Shown as the first option; only selectable when no value is set. Setting <code>prompt:</code> suppresses the default blank option.</td>
</tr>
<tr>
<th class="l-ui-table__cell l-ui-table__cell--primary" scope="row"><code>include_blank:</code></th>
<td class="l-ui-table__cell">Boolean / String</td>
<td class="l-ui-table__cell">For <code>:select</code> fields. Defaults to <code>true</code>. Pass a string to use it as the blank option's label, or <code>false</code> to omit the blank option entirely.</td>
</tr>
</tbody>
</table>
</div>
Loading