LearnNewsExamplesServices
Frontmatter
id5851
titlelist config: useCheckboxes: true checkbox -- selection fails in neo 7.0.6
stateClosed
labels
bug
assignees[]
createdAtSep 3, 2024, 6:38 AM
updatedAtSep 4, 2024, 2:13 AM
githubUrlhttps://github.com/neomjs/neo/issues/5851
authorgplanansky
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtSep 3, 2024, 4:43 PM

list config: useCheckboxes: true checkbox -- selection fails in neo 7.0.6

Closed v8.1.0 bug
gplanansky
gplanansky commented on Sep 3, 2024, 6:38 AM

Describe the bug

With the list configured: useCheckboxes: true, checkboxes appear but they stay empty when clicked.

It works in neo 6.10, where selection/model: select(...) gets invoked and adds the value "neo-selected" to the class. In neo 7.0.6, select() is not invoked.

To Reproduce 0. install as normal: git clone neo 7.0.6: NEO_CODE_BLOCK_0

  1. Modify examples/todoList/version2 config with useCheckBoxes: true to get checkboxes:

NEO_CODE_BLOCK_1

NEO_CODE_BLOCK_2

  1. run dev server as usual:

NEO_CODE_BLOCK_3 3. in Chrome, open examples/todoList/version2

  1. click on first item (empty) checkbox checkbox stays empty

Expected behavior checkbox shows check

Screenshots devtools elements

  1. on start, no click yet

examples-todoList-version2-start

  1. click on first item check box

    examples-todoList-version2-clicked-first-item

  2. edit cls to add neo-selected => checkmark appears

    examples-todoList-version2-edit-add-neo-selected

Desktop (please complete the following information):

  • OS: macos
  • Browser chrome
  • Version 128.0.6613.114 (Official Build) (arm64)

Additional context in neo 6.10.10, the click invokes:

selection/Model.mjs: select(items, itemCollection=this.items, selectedCls)

which add the "neo-selected" class value,

in neo 7.0.6, the click goes to main/addon/Navigator

and disappears. A breakpoint in in selection/Model.mjs: select() is not exercised.

gplanansky added the bug label on Sep 3, 2024, 6:38 AM
tobiu
tobiu Sep 3, 2024, 4:40 PM

Hi George,

a good catch, almost took me 10m :)

Let me describe how I debugged it, to get some insights how to do it.

First I checked examples.list.Base, which has a useCheckBoxes option on the right. Worked.

Then I recalled that I was using almost the same code inside the learning section:

Screenshot 2024-09-03 at 16 31 24

Knowing that it should work in general, I just needed to figure out, why neo-selected did not get applied.

Lists are using item ids in the following format: neo-list-1__tobiu

In depth:

    /**
     * @param {Number|String|object} recordOrId
     * @returns {String}
     */
    getItemId(recordOrId) {
        return `${this.id}__${recordOrId.isRecord ? recordOrId[this.getKeyProperty()] : recordOrId}`
    }

/**
 * @param {String} vnodeId
 * @returns {String|Number} itemId
 */
getItemRecordId(vnodeId) {
    let itemId   = vnodeId.split('__')[1],
        {model}  = this.store,
        keyField = model?.getField(model.keyProperty),
        keyType  = keyField?.type?.toLowerCase();

    if (keyType === 'int' || keyType === 'integer') {
        itemId = parseInt(itemId)
    }

    return itemId
}

The important part: ids inside the DOM are always strings. So, when trying to get the record via an recordId, we do need to know if this one is a string (default) or an integer.

And this already was the root cause: inside examples.todoList.version2.TodoListModel, the id field had the invalid type Number.

I will push the fix now.

Follow up idea: it would be nice to decouple useCheckBoxes optionally from selections and just match another boolean record field (new ticket). Maybe i already created this one.

tobiu referenced in commit 65fe53a - "#5851 examples.todoList.version2.TodoListModel: fixing the invalid type for the id field, useCheckBoxes: true for the list" on Sep 3, 2024, 4:42 PM
tobiu closed this issue on Sep 3, 2024, 4:43 PM
gplanansky
gplanansky Sep 4, 2024, 2:12 AM

Thanks.

I missed catching the difference of list Base.mjs getItemRecordId returning 1 vs "1" .

In selection/ListModel.mjs : onListClick, view.store.get("1") returns null.

onListClick({ currentTarget }) {
        let {view} = this,
            record;

    if (!view.disableSelection) {
        record = view.store.get(view.getItemRecordId(currentTarget));

        record && this.select(record)
    }
}

So, in 6.10.10, and going back to 4.0.89, the test was for 'integer' or 'number':

      getItemRecordId(vnodeId) {
        let itemId   = vnodeId.split('__')[1],
            model    = this.store.model,
            keyField = model?.getField(model.keyProperty),
            keyType  = keyField?.type.toLowerCase();

    if (keyType === 'integer' || keyType === 'number') {
        itemId = parseInt(itemId);
    }

    return itemId;
}

Prior, in 2019 the test was for number only:

    getItemRecordId(vnodeId) {
        let itemId   = vnodeId.split('__')[1],
            model    = this.store.model,
            keyField = model && model.getField(model.keyProperty);

    if (keyField && keyField.type.toLowerCase() === 'number') {
        itemId = parseInt(itemId);
    }

    return itemId;
}

Why the changes?