https://discord.umbraco.com logo
Umbsortercontroller thingy
# umbraco-chat
b
I'm working with UmbSorterController, am I understanding this correct? if I'm working with observable data do I have to reinitialize the entire controller every time? just using setModel on a sortcontroller that was created on connectedCallback doesnt seem to work when the observable data changes
r
The core issue: UmbSorterController holds an internal reference to the array you pass via setModel. When your observable data changes, it emits a new array reference — but the sorter controller is still pointing at the old one. Calling setModel again with the new array should work in theory, but there's a subtlety: The sorter also manages DOM node → model item mapping internally. If the DOM hasn't re-rendered yet when you call setModel, the mapping gets out of sync. This is especially common with LitElement's async rendering cycle.
I’ve had this issue I out this into Ai to get this .. and I pasted that because my original text was a random word mess that would have taken you longer to understand stand
The correct pattern is to call setModel after the render cycle has completed, using this.updateComplete: tsthis._observe(this.someObservableData, (data) => { this._model = data ?? []; this.requestUpdate(); this.updateComplete.then(() => { this._sorterController.setModel(this._model); }); }); You do NOT need to reinitialize the controller — that's the good news. The controller itself is fine to create once in connectedCallback. The trick is just ensuring the DOM is in sync before you update the model reference. Alternatively, if your items are rendered via a repeat() directive with stable keys, the sorter can track items more reliably. Make sure you're using repeat with a key function rather than mapping directly: ts// Prefer this ${repeat(this._model, (item) => item.unique, (item) => html`...
Copy code
)}

// Over this
${this._model.map(item => html
...`)} Without stable keys, Lit recycles DOM nodes in ways that confuse the sorter's internal node↔item map.
b
yeah tried that approach, but it seems very like very funky behavior to me when using that in the connectedCallback lifecycle
Copy code
private _initializeSorter(model: Field[]) {
    if (this.sorter) {
      this.sorter.destroy()
    }
    this.sorter = new UmbSorterController<Field>(this, {
      itemSelector: '.sorter-item',
      containerSelector: '.sorter-container',
      getUniqueOfElement: (element) => {
        return element.getAttribute('data-sorter-id')
      },
      getUniqueOfModel: (modelEntry) => {
        return modelEntry.id
      },
      onChange: async ({ model }) => {
        const context = await this.getContext(FormsEditorContext_TOKEN)
        if (!context) {
          return
        }

        const newFieldSets = this.page.fieldSets.map((fieldSet) => ({
          ...fieldSet,
          containers: fieldSet.containers.map((container) => ({
            ...container,
            fields: [...model],
          })),
        }))

        context.updatePage(this.page.id, {
          fieldSets: newFieldSets,
        })
      },
    })
    this.sorter.setModel(model)
  }
doing cleanup of any previous sorters now, it still feels kind of jank but oh well
r
There is something else but it’s Beena while and I think there might be something else or better .. but I can’t remember where or what I did .. the things with age
b
if you can remember what it was that'd be fantastic! my method also has some quirks with sorting sadly
r
All I would say is post to the forum and wait.. unfortunately it’s a quiet time with everyone who could help at codegarden, so you might have to be more patient than usual
b
I just came back with a new insight, using the sorter in a complex rendering structure with layered repeats is a no go
I moved the sorter and rendering logic to its own component so that the sort-container and underlying sort-item elements are in the same element and that seems to work
r
Ah that sort of makes sense in the abstract..
b
guess the repeat breaks the observers for new sort item elements somehow? still weird that it would work with existing items
3 Views