Skip to content
Closed
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
125 changes: 72 additions & 53 deletions app/javascript/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,59 +53,78 @@ import ToggleController from './controllers/toggle_controller'
import TrixBodyController from './controllers/trix_body_controller'
import TrixFieldController from './controllers/fields/trix_field_controller'

application.register('action', ActionController)
application.register('actions-overflow', ActionsOverflowController)
application.register('actions-picker', ActionsPickerController)
application.register('attachments', AttachmentsController)
application.register('boolean-filter', BooleanFilterController)
application.register('card-filters', CardFiltersController)
application.register('clear-input', ClearInputController)
application.register('copy-to-clipboard', CopyToClipboardController)
application.register('dashboard-card', DashboardCardController)
application.register('date-time-filter', DateTimeFilterController)
application.register('filter', FilterController)
application.register('form', FormController)
application.register('hidden-input', HiddenInputController)
application.register('input-autofocus', InputAutofocusController)
application.register('item-select-all', ItemSelectAllController)
application.register('item-selector', ItemSelectorController)
application.register('loading-button', LoadingButtonController)
application.register('media-library-attach', MediaLibraryAttachController)
application.register('media-library', MediaLibraryController)
application.register('menu', MenuController)
application.register('modal', ModalController)
application.register('multiple-select-filter', MultipleSelectFilterController)
application.register('avo-nested-form', NestedFormController)
application.register('panel-refresh', PanelRefreshController)
application.register('per-page', PerPageController)
application.register('preview', PreviewController)
application.register('record-selector', RecordSelectorController)
application.register('resource-edit', ResourceEditController)
application.register('resource-index', ResourceIndexController)
application.register('resource-show', ResourceShowController)
application.register('search', SearchController)
application.register('select-filter', SelectFilterController)
application.register('select', SelectController)
application.register('self-destroy', SelfDestroyController)
application.register('sidebar', SidebarController)
application.register('sign-out', SignOutController)
application.register('table-row', TableRowController)
application.register('tabs', TabsController)
application.register('text-filter', TextFilterController)
application.register('tippy', TippyController)
application.register('toggle', ToggleController)
application.register('trix-body', TrixBodyController)
// Special cases for controller registration names
const SPECIAL_CASES = {
nested_form: 'avo-nested-form'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to not make this like the others and eliminate the special cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, since we're extending NestedForm from 'stimulus-rails-nested-form', and the common way to import this controller is as nested-form, it was causing conflicts with parent apps that also use nested-form.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related PR #3864

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. but what stops us to name it like that?

data-controller="avo-nested-form"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or, change the name that we can change

Copy link
Contributor Author

@Paul-Bob Paul-Bob Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry could you rephrase? I didn't get your question


I will assume that by "like that" you mean nested-form.

There are apps using avo that also import stimulus-rails-nested-form and register it under the same name: nested-form. This results in two controllers being registered with the same identifier.

In the app where I encountered and resolved this issue (via the PR linked above), the conflict manifested as duplicate behavior: clicking the "add" button, which was using data-controller="nested-form" would create two new entries per click, one from our (avo) controller and one from the parent app's controller.

}

// Field controllers
application.register('belongs-to-field', BelongsToFieldController)
application.register('code-field', CodeFieldController)
application.register('date-field', DateFieldController)
application.register('easy-mde', EasyMdeController)
application.register('key-value', KeyValueController)
application.register('progress-bar-field', ProgressBarFieldController)
application.register('reload-belongs-to-field', ReloadBelongsToFieldController)
application.register('tags-field', TagsFieldController)
application.register('tiptap-field', TiptapFieldController)
application.register('trix-field', TrixFieldController)
// Helper function to convert snake_case to kebab-case
function toKebabCase(str) {
return str.replace(/_/g, '-')
}

// Controllers registry - automatically registers all controllers
const CONTROLLERS = [
['action', ActionController],
Copy link
Collaborator

@adrianthedev adrianthedev Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And we then can infer the names.
So in teh end we'd end up with somethign like this

import ActionController from ...
import ...
import ...

registerControllers(application, [Actioncontroller, ..., ...])

it would be easier for us to implement this as well
#2030

['actions_overflow', ActionsOverflowController],
['actions_picker', ActionsPickerController],
['attachments', AttachmentsController],
['boolean_filter', BooleanFilterController],
['card_filters', CardFiltersController],
['copy_to_clipboard', CopyToClipboardController],
['dashboard_card', DashboardCardController],
['date_time_filter', DateTimeFilterController],
['filter', FilterController],
['form', FormController],
['hidden_input', HiddenInputController],
['input_autofocus', InputAutofocusController],
['item_select_all', ItemSelectAllController],
['item_selector', ItemSelectorController],
['loading_button', LoadingButtonController],
['media_library_attach', MediaLibraryAttachController],
['media_library', MediaLibraryController],
['menu', MenuController],
['modal', ModalController],
['multiple_select_filter', MultipleSelectFilterController],
['nested_form', NestedFormController],
['panel_refresh', PanelRefreshController],
['per_page', PerPageController],
['preview', PreviewController],
['record_selector', RecordSelectorController],
['resource_edit', ResourceEditController],
['resource_index', ResourceIndexController],
['resource_show', ResourceShowController],
['search', SearchController],
['select', SelectController],
['select_filter', SelectFilterController],
['self_destroy', SelfDestroyController],
['sidebar', SidebarController],
['sign_out', SignOutController],
['table_row', TableRowController],
['tabs', TabsController],
['text_filter', TextFilterController],
['tippy', TippyController],
['toggle', ToggleController],
['trix_body', TrixBodyController],

// Field controllers
['belongs_to_field', BelongsToFieldController],
['clear_input', ClearInputController],
['code_field', CodeFieldController],
['date_field', DateFieldController],
['easy_mde', EasyMdeController],
['key_value', KeyValueController],
['progress_bar_field', ProgressBarFieldController],
['reload_belongs_to_field', ReloadBelongsToFieldController],
['tags_field', TagsFieldController],
['tiptap_field', TiptapFieldController],
['trix_field', TrixFieldController],
]

// Auto-register all controllers
CONTROLLERS.forEach(([controllerName, ControllerClass]) => {
const registrationName = SPECIAL_CASES[controllerName] || toKebabCase(controllerName)
application.register(registrationName, ControllerClass)
})

// Custom controllers
Loading