Configuration
Avo version
Beta 58
Rails version
8.1.3
Ruby version
3.3.4
License type
Are you using Avo monkey patches, overriding views or view components?
Description
It seems as though stimulus controllers that run, do not get run when in nested mode on create/edit.
Additional context
tab title: "Companies" do
field :companyables, as: :has_many,
nested: { on: :forms, limit: 10 }
end
Not sure if you need the full controller but thought i'd post it to save you having to ask:
import { Controller } from "@hotwired/stimulus";
const LOADER_CLASSES = "absolute bg-gray-100 opacity-10 w-full h-full";
export default class extends Controller {
static targets = ["companyFieldInput", "modelFieldInput", "submodelFieldInput", "companyHasManyWrapper", "modelBelongsToWrapper", "submodelBelongsToWrapper"];
static values = {
view: String,
};
static initialModelValue;
static initialSubmodelValue;
// get placeholder() {
// return this.modelFieldInputTarget.options[0];
// }
set loading(isLoading) {
if (isLoading) {
// create a loader overlay
const loadingDiv = document.createElement("div");
loadingDiv.className = LOADER_CLASSES;
loadingDiv.dataset.target = "model-loader";
// add the loader overlay
this.modelBelongsToWrapperTarget.prepend(loadingDiv);
this.modelBelongsToWrapperTarget.classList.add("opacity-50");
} else {
// remove the loader overlay
this.modelBelongsToWrapperTarget
.querySelector('[data-target="model-loader"]')
.remove();
this.modelBelongsToWrapperTarget.classList.remove("opacity-50");
}
}
async connect() {
// Add the controller functionality only on forms
if (["edit", "new"].includes(this.viewValue)) {
if (this.hasModelFieldInputTarget) this.captureTheInitialModelValue();
if (this.hasSubmodelFieldInputTarget) this.captureTheInitialSubmodelValue();
// Trigger the change on load
await this.onCompanyChange();
await this.onModelChange();
}
}
// Read the company select.
// If there's any value selected show the models and prefill them.
async onCompanyChange() {
if (this.hasCompanyFieldInputTarget && this.hasModelFieldInputTarget) {
// Get the company
const company = this.companyFieldInputTarget.value;
// Dynamically fetch the models for this company
const models = await this.fetchModelsForCompany(company);
// Clear the select of options
Object.keys(this.modelFieldInputTarget.options).forEach(() => {
this.modelFieldInputTarget.options.remove(0);
});
// Add blank option
this.modelFieldInputTarget.add(new Option("Select a Model", ""));
// Add the new models
models.forEach((model) => {
this.modelFieldInputTarget.add(new Option(model.name, model.id));
});
// Check if the initial value is present in the models array and select it.
// If not, select the first item
const currentOptions = Array.from(this.modelFieldInputTarget.options).map(
(item) => item.value
);
if (currentOptions.includes(this.initialModelValue)) {
this.modelFieldInputTarget.value = this.initialModelValue;
} else {
// Select the first item
this.modelFieldInputTarget.value = this.modelFieldInputTarget.options[0].value;
}
}
}
// Read the model select.
// If there's any value selected show the submodels and prefill them.
async onModelChange() {
if (this.hasCompanyFieldInputTarget && this.hasModelFieldInputTarget && this.hasSubmodelFieldInputTarget) {
// Get the company
const company = this.companyFieldInputTarget.value;
// Get the model
const model = this.modelFieldInputTarget.value;
// Dynamically fetch the models for this company
const submodels = await this.fetchSubmodelsForModel(model);
// Clear the select of options
Object.keys(this.submodelFieldInputTarget.options).forEach(() => {
this.submodelFieldInputTarget.options.remove(0);
});
// Add blank option
this.submodelFieldInputTarget.add(new Option("Select a Submodel", ""));
// Add the new models
submodels.forEach((submodel) => {
this.submodelFieldInputTarget.add(new Option(submodel.name, submodel.id));
});
// Check if the initial value is present in the models array and select it.
// If not, select the first item
const currentOptions = Array.from(this.submodelFieldInputTarget.options).map(
(item) => item.value
);
if (currentOptions.includes(this.initialSubmodelValue)) {
this.submodelFieldInputTarget.value = this.initialSubmodelValue;
} else {
// Select the first item
this.submodelFieldInputTarget.value = this.submodelFieldInputTarget.options[0].value;
}
}
}
captureTheInitialModelValue() {
this.initialModelValue = this.modelFieldInputTarget.value;
}
captureTheInitialSubmodelValue() {
this.initialSubmodelValue = this.submodelFieldInputTarget.value;
}
async fetchModelsForCompany(company) {
if (!company) {
return [];
}
this.loading = true;
const response = await fetch(
`${window.Avo.configuration.root_path}/companies/models?company=${encodeURIComponent(company)}`
);
const data = await response.json();
this.loading = false;
return data;
}
async fetchSubmodelsForModel(model) {
if (!model) {
return [];
}
this.loading = true;
const response = await fetch(
`${window.Avo.configuration.root_path}/companies/models/submodels?model=${model}`
);
const data = await response.json();
this.loading = false;
return data;
}
}
Screenshots or screen recordings
In the screenshot, that select box should already have filtered down to a much smaller set of options. Works fine when not in nested mode.

Configuration
Avo version
Beta 58
Rails version
8.1.3
Ruby version
3.3.4
License type
Are you using Avo monkey patches, overriding views or view components?
Description
It seems as though stimulus controllers that run, do not get run when in nested mode on create/edit.
Additional context
Not sure if you need the full controller but thought i'd post it to save you having to ask:
Screenshots or screen recordings
In the screenshot, that select box should already have filtered down to a much smaller set of options. Works fine when not in nested mode.