突然无法选中 Svelte 复选框
Svelte checkboxes suddenly can't be checked
下面是重现我的问题的代码 (Svelte 3.0.0)。
重现步骤:
- 单击一个复选框。 (表现正常)
- 在搜索框中输入一些字符。
- 删除您刚刚输入的字符。
- 再次单击复选框。请注意,现在它没有任何效果。复选框保持空白。
EDIT: 好像跟这行有关:
bind:group={selectedVars[schemaVar.name].lts}
如果我将其硬编码为:
bind:group={selectedVars['bar'].lts}
然后它工作正常。
知道为什么过滤器会破坏复选框吗?
<script>
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
$: availableLTs = ["aaa", "bbb", "ccc", "abc"];
function matchesSearch(searchString, text) {
let query = searchString;
console.log("query is", query);
if (!query) return true;
return text.includes(query);
}
let selectedChart = 'bar';
let selectedVars = {X: { lts: [] }};
$: schemaVars = schema.vars;
let searchString = "";
</script>
<main>
{#each schemaVars as schemaVar}
<h6>
{schemaVar.name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
{#each availableLTs as ele}
{#if matchesSearch(searchString, ele)}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={selectedVars[schemaVar.name].lts}
value={ele}
/>
{ele}
</label>
</div>
{/if}
{/each}
{/each}
</main>
你可以这样解决这个问题
在App.Svelte
<script>
import Checkbox from './Checkbox.svelte';
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
$: availableLTs = ["aaa", "bbb", "ccc", "ABC"];
$: matchesSearch = availableLTs.filter((elem) =>{ return elem.includes(searchString); })
let selectedChart = 'bar';
let selectedVars = {X: { lts: [] }};
$: console.log(selectedVars)
$: schemaVars = schema.vars;
let searchString = "";
</script>
<main>
{#each schemaVars as {name}}
<h6>
{name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
<Checkbox bind:value={selectedVars} {name} {matchesSearch}/>
{/each}
</main>
在Checkbox.Svelte
<script>
export let value, name, matchesSearch;
</script>
{#each matchesSearch as ele}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={value[name].lts}
value={ele}
/>
{ele}
</label>
</div>
{/each}
你可以在这个repl
中查看
看起来问题与嵌套的 each 循环有关
{#each schemaVars as schemaVar}
...
{#each availableLTs as ele}
...//Checkbox
{/each}
{/each}
可以通过将内部循环包装在组件中来解决。
前面的回答差不多解决了问题,但是漏掉了一个重要的东西:
组件内的每个循环不是 "keyed each block" ->
- select第三个复选框'ccc'
- 过滤 'c'
- -> 'ccc' 移动到第一个位置,不再检查
(或者 select 'aaa' 并过滤 'b'...)
这可以通过将标签文本添加为 key/id 来解决(假设复选框标签是唯一的)->
{#each filteredLTs as ele (ele)}
...
{/each}
因为问题不在于变量的设置方式 (...selectedVars[[=47=]].lts}),我会尽量保持组件内部的逻辑通用并在 App.svelte 内的组件标签内专门设置变量 -> 组件保持通用并且可以轻松重用
Example in this REPL
[App.svelte]
<script>
import Checkboxes from './Checkboxes.svelte'
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
let allLTs = ["aaa", "bbb", "ccc", "abc"];
let searchString = "";
$: filteredLTs = allLTs.filter(lt => lt.includes(searchString))
let selectedVars = {X: { lts: [] }};
$: console.log(selectedVars.X.lts)
</script>
<main>
{#each schema.vars as schemaVar}
<h6>
{schemaVar.name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
<div class="form-check">
<Checkboxes checkboxes={filteredLTs} bind:checked={selectedVars[schemaVar.name].lts}/>
</div>
{/each}
</main>
[Checkboxes.svelte]
<script>
export let checkboxes, checked
</script>
{#each checkboxes as checkbox (checkbox)}
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={checked}
value={checkbox}
/>
{checkbox}
</label>
{/each}
下面是重现我的问题的代码 (Svelte 3.0.0)。
重现步骤:
- 单击一个复选框。 (表现正常)
- 在搜索框中输入一些字符。
- 删除您刚刚输入的字符。
- 再次单击复选框。请注意,现在它没有任何效果。复选框保持空白。
EDIT: 好像跟这行有关:
bind:group={selectedVars[schemaVar.name].lts}
如果我将其硬编码为:
bind:group={selectedVars['bar'].lts}
然后它工作正常。
知道为什么过滤器会破坏复选框吗?
<script>
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
$: availableLTs = ["aaa", "bbb", "ccc", "abc"];
function matchesSearch(searchString, text) {
let query = searchString;
console.log("query is", query);
if (!query) return true;
return text.includes(query);
}
let selectedChart = 'bar';
let selectedVars = {X: { lts: [] }};
$: schemaVars = schema.vars;
let searchString = "";
</script>
<main>
{#each schemaVars as schemaVar}
<h6>
{schemaVar.name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
{#each availableLTs as ele}
{#if matchesSearch(searchString, ele)}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={selectedVars[schemaVar.name].lts}
value={ele}
/>
{ele}
</label>
</div>
{/if}
{/each}
{/each}
</main>
你可以这样解决这个问题
在App.Svelte
<script>
import Checkbox from './Checkbox.svelte';
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
$: availableLTs = ["aaa", "bbb", "ccc", "ABC"];
$: matchesSearch = availableLTs.filter((elem) =>{ return elem.includes(searchString); })
let selectedChart = 'bar';
let selectedVars = {X: { lts: [] }};
$: console.log(selectedVars)
$: schemaVars = schema.vars;
let searchString = "";
</script>
<main>
{#each schemaVars as {name}}
<h6>
{name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
<Checkbox bind:value={selectedVars} {name} {matchesSearch}/>
{/each}
</main>
在Checkbox.Svelte
<script>
export let value, name, matchesSearch;
</script>
{#each matchesSearch as ele}
<div class="form-check">
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={value[name].lts}
value={ele}
/>
{ele}
</label>
</div>
{/each}
你可以在这个repl
中查看看起来问题与嵌套的 each 循环有关
{#each schemaVars as schemaVar}
...
{#each availableLTs as ele}
...//Checkbox
{/each}
{/each}
可以通过将内部循环包装在组件中来解决。
前面的回答差不多解决了问题,但是漏掉了一个重要的东西: 组件内的每个循环不是 "keyed each block" ->
- select第三个复选框'ccc'
- 过滤 'c'
- -> 'ccc' 移动到第一个位置,不再检查
(或者 select 'aaa' 并过滤 'b'...)
这可以通过将标签文本添加为 key/id 来解决(假设复选框标签是唯一的)->
{#each filteredLTs as ele (ele)}
...
{/each}
因为问题不在于变量的设置方式 (...selectedVars[[=47=]].lts}),我会尽量保持组件内部的逻辑通用并在 App.svelte 内的组件标签内专门设置变量 -> 组件保持通用并且可以轻松重用 Example in this REPL
[App.svelte]
<script>
import Checkboxes from './Checkboxes.svelte'
let schema = {
name: "bar",
vars: [{ name: "X" }],
};
let allLTs = ["aaa", "bbb", "ccc", "abc"];
let searchString = "";
$: filteredLTs = allLTs.filter(lt => lt.includes(searchString))
let selectedVars = {X: { lts: [] }};
$: console.log(selectedVars.X.lts)
</script>
<main>
{#each schema.vars as schemaVar}
<h6>
{schemaVar.name}
<input type="text" bind:value={searchString} placeholder="Search..." />
</h6>
<div class="form-check">
<Checkboxes checkboxes={filteredLTs} bind:checked={selectedVars[schemaVar.name].lts}/>
</div>
{/each}
</main>
[Checkboxes.svelte]
<script>
export let checkboxes, checked
</script>
{#each checkboxes as checkbox (checkbox)}
<label>
<input
type="checkbox"
class="form-check-input"
bind:group={checked}
value={checkbox}
/>
{checkbox}
</label>
{/each}