如何将这个待办事项列表与 Svelte 中的即时搜索结合起来? [英] How to marry this todo list with instant search in Svelte?

查看:31
本文介绍了如何将这个待办事项列表与 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:

  1. 当页面加载时,表单域应该是焦点.
  2. 当用户单击向上/向下箭头时,应通过 CSS 背景颜色更改来选择列表中的项目.
  3. 当用户在表单中键入新项目时,它应该出现在用户列表中.
  4. 当用户在表单字段中键入时,即时搜索"会出现.应用于列表,只显示与搜索匹配的项目.所有其他功能应该仍然有效.当用户使用向上/向下箭头滚动时,无论页面上显示多少项,它都应该仍然有效.如果只显示两个项目,用户应该能够使用向上向下箭头选择这两个项目和表单域焦点.

除 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆