binding
binding copied to clipboard
Binding checkboxes: custom matcher does not work when using repeat.for
I'm submitting a bug report
- Library Version: 2.5.2
Please tell us about your environment:
-
Operating System: Windows 10
-
Node Version: 10.18.0
-
NPM Version: 6.13.4
-
JSPM OR Webpack AND Version JSPM 0.16.55
-
Browser: Chrome 80.0.3987.149 | Firefox 74.0.1 | Edge 44.18362.449.0 (non-Chromium) | most likely all
-
Language: TypeScript 3.7.5
Current behavior: According to the documentation about binding checkboxes, it is possible to use a custom matcher to determine whether a checkbox with an object as its model should be checked. However, this does not seem to work properly for lists of checkboxes dynamically built with repeat.for: it does mostly work when selecting items, but not when there is already a list of selected items.
Here is an example forked from the one in the documentation which shows how the repater context is the problem, as when options are written manually everything works correctly.
Reposting here both code files for reproducibility:
app.ts
export class App {
availableProducts = [
{ id: 0, name: "Motherboard" },
{ id: 1, name: "CPU" },
{ id: 2, name: "Memory" }
];
selectedProducts = [{ id: 1, name: "CPU" }, { id: 2, name: "Memory" }];
productMatcher = (a, b) => {
console.log(a, "?=", b); // does not get triggered in the repeater context
return a.id === b.id;
};
}
app.html
<template>
<form>
<h3>Available items</h3>
<ul>
<li repeat.for="p of availableProducts">
${p.id} - ${p.name}
</li>
</ul>
<hr />
<h3>Checkbox list (manual)</h3>
<label>
<input
type="checkbox"
model.bind="availableProducts[0]"
matcher.bind="productMatcher"
checked.bind="selectedProducts"
/>
${availableProducts[0].name}
</label>
<label>
<input
type="checkbox"
model.bind="availableProducts[1]"
matcher.bind="productMatcher"
checked.bind="selectedProducts"
/>
${availableProducts[1].name}
</label>
<label>
<input
type="checkbox"
model.bind="availableProducts[2]"
matcher.bind="productMatcher"
checked.bind="selectedProducts"
/>
${availableProducts[2].name}
</label>
<h3>Checkbox list (with repeater)</h3>
<label repeat.for="p of availableProducts">
<input
type="checkbox"
model.bind="p"
matcher.bind="productMatcher"
checked.bind="selectedProducts"
/>
${p.name}
</label>
<hr />
<h3>Selected items</h3>
<ul>
<li repeat.for="product of selectedProducts">
${product.id} - ${product.name}
</li>
</ul>
</form>
</template>
Expected/desired behavior: Considering having a multiple-item selector with a dynamic number of options seems a common use-case, it should be possible to use a custom matcher in the context of a repeater.
@m-gallesio thanks for creating this issue. It's a bug with the repeater/matcher combo that got fixed awhile ago, without proper documentation update. Here is the working example https://codesandbox.io/s/object-matcher-not-working-with-repeater-5sbvz
Notice in main.ts
, we have this line:
Repeat.useInnerMatcher = false;
Its job is to fix a bug where the repeat would look into its template and extract the matcher there, which is wrong in the example you gave, because it belongs to the checkbox.
The reason it's not false
by default is backward compatibility.
The PR is here https://github.com/aurelia/templating-resources/pull/379
If this help fix your issue, please consider help update the docco for this 😬
It works, thank you very much for your attention. (Also it seems I opened this in the wrong repository.) As for the documentation, how will Aurelia 2 handle this case?
At the moment, we support matcher on input. And @fkleuver is working on the matcher for repeat. So for your scenario, it should work fine, the same way. The doc we lack currently is for v1 and the changes above though.