如何将这个待办事项列表与 Svelte 中的即时搜索结合起来? [英] How to marry this todo list with instant search in Svelte?
问题描述
编辑 tldr 版本向下滚动到它说的位置我非常接近下面的代码.
EDIT for the tldr version scroll down to where it says I'm extremely close in the code below.
问题
我有一个基本的待办事项清单,完成后将具有以下特点:
I have a basic todo list that when completed will have these qualities:
- 当页面加载时,表单域应该是焦点.
- 当用户单击向上/向下箭头时,应通过 CSS 背景颜色更改来选择列表中的项目.
- 当用户在表单中键入新项目时,它应该出现在用户列表中.
- 当用户在表单字段中键入时,即时搜索"会出现.应用于列表,只显示与搜索匹配的项目.所有其他功能应该仍然有效.当用户使用向上/向下箭头滚动时,无论页面上显示多少项,它都应该仍然有效.如果只显示两个项目,用户应该能够使用向上向下箭头选择这两个项目和表单域焦点.
除 4 以外的所有项目似乎都运行良好.以下代码演示了第 1-3 项
All items except number 4 seem to work fine. The following code demonstrates items 1-3
https://svelte.dev/repl/214b9c033d1c489e991484d387c267c2?version=3.30.0"
<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"];
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});
function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;
indexVal = indexVal < 0 ? clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ? 0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus();
} else {
clientInputTextField.blur()
}
}
function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>
<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField} bind:value={clientVal} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>
<!--
function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});
console.log(filteredCharacters)
}
-->
我想将上面的代码与即时搜索功能结合起来.
I want to marry the above code with an instant search feature.
function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});
console.log(filteredCharacters)
}
到目前为止我所尝试的一切都只是一团糟,不返回列表并且不聚焦(onBlur)输入字段.
Everything I've tried so far just makes a mess, does not return the list and unfocuses (onBlur) the input field.
console.log 下面的代码是一个数组,当用户搜索时,它给了我我想要的东西.下一步是将它应用到 DOM.到目前为止我尝试过的所有方法都没有奏效.
The code below console.log's an array that gives me what I want as the user searches. The next step is to apply it to the DOM. Everything I've tried so far has not worked.
https://svelte.dev/repl/ceca685a3a4c47b4b4b5ccd780a101fc63?version=3.30.0"
<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"];
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});
function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});
console.log(filteredCharacters)
}
function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;
indexVal = indexVal < 0 ? clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ? 0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus();
} else {
clientInputTextField.blur()
}
}
function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>
<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField} bind:value={clientVal} on:input={search} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>
<!--
-->
编辑
我非常接近下面的代码.
在这个版本中,唯一的问题是当用户提交一个新的待办事项时,列表不会出现在 DOM 中.幕后的其他一切都有效.要了解我的意思,请在输入字段中添加一个项目,提交它,然后在表单字段中键入字母 a,然后按退格按钮.列表将重新出现.
In this version, the only problem is that when a user submits a new todo the list does not appear in the DOM. Everything else behind the scenes works. To see what I mean, add an item to the input field, submit it and then type the letter a in the form field and then hit the back space button. The list will reappear.
https://svelte.dev/repl/f8fb733401eb4e27b9b8e54c688d355a?version=3.30.0"
<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"];
let clientsCopy = [...clients];
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
onMount(function() {
clientInputTextField.focus();
});
function search(e){
console.log(e.target.value)
const searchString = e.target.value.toLowerCase();
const filteredCharacters = clients.filter((character) => {
return (
character.toLowerCase().includes(searchString) ||
character.toLowerCase().includes(searchString)
);
});
clientsCopy = [...filteredCharacters]
}
function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;
indexVal = indexVal < 0 ? clientsCopy.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clientsCopy.length ? 0 : indexVal
console.log(indexVal);
}
if(indexVal > clientsCopy.length -1 || indexVal < 0){
clientInputTextField.focus();
} else {
clientInputTextField.blur()
}
}
function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>
<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<input type="text" name="input" bind:this={clientInputTextField} bind:value={clientVal} on:input={search} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each clientsCopy as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>
<!--
-->
推荐答案
这是一个更简洁的版本,基于 gist 中的代码此处.不过,它实际上与您的解决方案相同(即创建和显示单独的过滤"列表)!
This is a little more succint version of what you have, based on code found in a gist here. It's effectively the same as your solution though (i.e. creating and displaying a separate "filtered" list)!
<script>
import { onMount } from 'svelte';
let clients = ["a Little piggy","b little piggy","c little piggy"];
let indexVal = -1;
let downArrowPress = 40;
let upArrowPress = 38;
let clientInputTextField = "";
let clientVal = "";
const startsWith = (item, query) => item.toLowerCase().indexOf(query.toLowerCase()) != -1;
$: filteredClients = clientVal && clientVal.length ? clients.filter(item => startsWith(item, clientVal)) : clients;
onMount(function() {
clientInputTextField.focus();
});
function handleKeydown(event) {
if(event.keyCode === upArrowPress) {
indexVal-=1;
indexVal = indexVal < 0 ? clients.length : indexVal
console.log(indexVal);
}
if(event.keyCode === downArrowPress) {
indexVal+=1;
indexVal = indexVal > clients.length ? 0 : indexVal
console.log(indexVal);
}
if(indexVal > clients.length -1 || indexVal < 0){
clientInputTextField.focus();
} else {
clientInputTextField.blur()
}
}
function onChange(e) {
console.log("what")
const searchTerm = e.target.value.toLowerCase();
console.log(searchTerm)
clients = clients.filter(client => client.toLowerCase().includes(searchTerm))
}
function handleSubmit(e) {
const value = e.target.input.value;
console.log(value);
clients = [...clients, value];
clientVal = "";
}
</script>
<svelte:window on:keydown={handleKeydown}/>
<form on:submit|preventDefault={handleSubmit}>
<!-- <input type="text" name="input" on:change={onChange} bind:this={clientInputTextField} bind:value={clientVal} autocomplete="off"> -->
<input type="text" name="input" bind:this={clientInputTextField} bind:value={clientVal} autocomplete="off">
<input type="submit" name="">
</form>
<ul>
{#each filteredClients as client, i}
{#if i === indexVal}
<li style="background-color:orange">{client}</li>
{:else}
<li style="">{client}</li>
{/if}
{/each}
</ul>
这篇关于如何将这个待办事项列表与 Svelte 中的即时搜索结合起来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!