FORMS_AND_WIDGETS(3) RSX Framework Manual FORMS_AND_WIDGETS(3) NAME Forms and Widgets - RSX form system with reusable widget components SYNOPSIS // Blade form markup // JavaScript - wire save button to form $('#save-btn').on('click', function() { const $form = $('.Rsx_Form').first(); $form.component().submit(); }); DESCRIPTION The RSX form system provides a clean separation between form structure (Rsx_Form), field layout (Form_Field), and input widgets (Text_Input, Select_Input, etc). This architecture enables: - Reusable widgets across all forms - Consistent validation error display - Automatic value collection and population - Test data generation via seeders - Read-only/disabled states - Custom field layouts without modifying widget code Key Components: - Rsx_Form: Container managing form submission and validation - Form_Field: Layout wrapper providing labels, help text, error display - Widgets: Reusable input components (Text_Input, Select_Input, etc) RSX_FORM COMPONENT The Rsx_Form component manages form data flow, submission, and validation. Required Attributes: $action - Controller method reference for form submission Example: Frontend_Clients_Controller.save Optional Attributes: $data - JSON-encoded object with initial form values Used for edit mode to populate fields Example: $data="{{ json_encode($client_data) }}" Methods: vals() - Get all form values as object vals(values) - Set all form values from object submit() - Submit form to $action endpoint seed() - Fill all fields with test data (debug mode only) Form Discovery: Rsx_Form automatically discovers all widgets using shallowFind('.Widget') and collects values based on their data-name attributes. No registration or manual wiring required. Example - Basic Form: Example - Edit Mode with Initial Data: @php $form_data = [ 'first_name' => $user->first_name, 'last_name' => $user->last_name, 'email' => $user->email, ]; @endphp FORM_FIELD WRAPPER Form_Field provides consistent layout for labels, help text, and error display. It wraps a single widget and connects it to the form. Required Attributes: $name - Field name for form serialization and error display Optional Attributes: $label - Label text displayed above field $required - Boolean, adds red asterisk to label $help - Help text displayed below field Responsibilities: - Display label with optional required indicator - Set data-name attribute on child widget - Display validation errors returned from server - Provide consistent spacing and styling Example - Basic Field: Example - Required Field with Help Text: Example - Field with HTML in Label: Custom Layout: Form_Field can be extended or replaced with custom jqhtml to change field layout. The only requirement is that the child widget must have the data-name attribute set to the field name. Example - Horizontal Layout:
<%= content() %> <% if (this.has_error()) { %>
<%= this.get_error() %>
<% } %>
WIDGET INTERFACE All form widgets must implement the standard widget interface: Required: - CSS class "Widget" on root element - val() method for getting current value - val(value) method for setting value Optional: - seed() method for generating test data - Support for $disabled attribute Widget Responsibilities: 1. Value Management Widgets must implement getter/setter via val() method: val() { // Getter - return current value if (arguments.length === 0) { return this.$id('input').val(); } // Setter - update value else { this.data.value = value || ''; this.$id('input').val(this.data.value); } } 2. Disabled State Widgets should respect $disabled attribute: - Render with disabled HTML attribute - Display grayed-out appearance - Still return value via val() getter - Do not submit in HTML form (handled by browser) 3. Test Data (Optional) Widgets may implement seed() for debug mode: async seed() { if (this.args.seeder) { // Generate test data this.val('Test Value'); } } BUILT-IN WIDGETS Text_Input Basic text input supporting multiple types and textarea. Attributes: $type - Input type (text, email, url, tel, number, textarea) $rows - Number of rows for textarea (default: 3) $placeholder - Placeholder text $prefix - Text to prepend (creates input-group) $suffix - Text to append (creates input-group) $min - Minimum value for number inputs $max - Maximum value for number inputs $maxlength - Maximum length for text inputs $disabled - Disable input (grayed out, still returns value) $seeder - Seeder function name for test data Examples: Select_Input Dropdown select with options. Attributes: $options - Array of options (see below) $placeholder - Placeholder option text $disabled - Disable select (grayed out, still returns value) $seeder - Seeder function name for test data Options Format: Simple array: ['Option 1', 'Option 2', 'Option 3'] Object array: [ {value: 'opt1', label: 'Option 1'}, {value: 'opt2', label: 'Option 2'} ] From Blade: $options="{{ json_encode($options_array) }}" Examples: @php $industries = ['Technology', 'Finance', 'Healthcare']; @endphp @php $sizes = [ ['value' => 'sm', 'label' => 'Small (1-10)'], ['value' => 'md', 'label' => 'Medium (11-50)'], ['value' => 'lg', 'label' => 'Large (50+)'], ]; @endphp Checkbox_Input Checkbox with optional label. Attributes: $label - Label text displayed next to checkbox $checked_value - Value when checked (default: "1") $unchecked_value - Value when unchecked (default: "0") $disabled - Disable checkbox (grayed out, still returns value) Examples: Wysiwyg_Input Rich text editor using Quill. Attributes: $placeholder - Placeholder text $disabled - Disable editor (not yet implemented) $seeder - Seeder function name for test data Example: SEEDING TEST DATA The seed system generates realistic test data for forms during development. Enabled only when window.rsxapp.debug is true. Seed Button: Rsx_Form automatically displays a "Fill Test Data" button in debug mode. Clicking this button calls seed() on all widgets. Widget Seeding: Widgets implement seed() to generate appropriate test data: async seed() { if (this.args.seeder) { // TODO: Implement Rsx_Random_Values endpoint let value = 'Test ' + (this.args.seeder || 'Value'); this.val(value); } } Seeder Names: Specify seeder via $seeder attribute: Future Implementation: Planned Rsx_Random_Values endpoint will provide: - company_name() - Random company names - email() - Random email addresses - phone() - Random phone numbers - first_name() - Random first names - last_name() - Random last names - address() - Random street addresses - city() - Random city names DISABLED STATE Disabled widgets display as read-only but still participate in form value collection. Behavior: - Widget displays grayed-out appearance - User cannot interact with widget - val() getter still returns current value - Value included in form submission via Ajax - HTML disabled attribute prevents browser form submission Example - Disable Individual Fields: Example - Conditional Disable: Use Cases: - Display data that cannot be edited - Show calculated or system-managed values - Enforce permissions (some users see but cannot edit) - Multi-step forms (disable completed steps) FORM SUBMISSION Form submission uses Ajax to send data to controller methods. JavaScript Submission: $('#save-btn').on('click', function() { const $form = $('.Rsx_Form').first(); const form_component = $form.component(); form_component.submit(); }); What Happens: 1. Form calls vals() to collect all widget values 2. Sends values to this.args.action via Ajax.call() 3. Handles response: - Success: Redirect if response.redirect provided - Validation errors: Display errors on fields - General errors: Log to console Controller Method: #[Ajax_Endpoint] public static function save(Request $request, array $params = []) { // Validation $validated = $request->validate([ 'email' => 'required|email', 'name' => 'required|string|max:255', ]); // Save data $user = User::create($validated); // Return response return [ 'success' => true, 'redirect' => Rsx::Route('Users_Controller', 'view', $user->id), ]; } Validation Errors: When validation fails, return errors in format: return [ 'success' => false, 'errors' => [ 'email' => 'The email field is required.', 'name' => 'The name field is required.', ], ]; Form automatically displays errors below each field. MULTI-COLUMN LAYOUTS Use Bootstrap grid for multi-column field layouts:
CREATING CUSTOM WIDGETS Create custom widgets by implementing the widget interface. Example - Rating Widget: File: rating_input.jqhtml
<% for (let i = 1; i <= 5; i++) { %> <% } %>
File: rating_input.js class Rating_Input extends Form_Input_Abstract { on_create() { this.data.value = 0; } on_ready() { const that = this; this.$.find('[data-rating]').on('click', function() { that.val($(this).data('rating')); }); } val(value) { if (arguments.length === 0) { return this.data.value; } else { this.data.value = value || 0; // Update star display this.$.find('[data-rating]').each(function() { const rating = $(this).data('rating'); $(this).toggleClass('bi-star-fill', rating <= value); $(this).toggleClass('bi-star', rating > value); }); } } async seed() { this.val(Math.floor(Math.random() * 5) + 1); } } Usage: EXAMPLES Complete Form Example: @php $form_data = isset($client) ? [ 'name' => $client->name, 'email' => $client->email, 'industry' => $client->industry, 'active' => $client->active, ] : []; $industries = ['Technology', 'Finance', 'Healthcare']; @endphp @if (isset($client)) @endif
SEE ALSO jqhtml(3), ajax(3), validation(3) RSX Framework October 2025 FORMS_AND_WIDGETS(3)