Svelte में तत्काल खोज के साथ इस टूडू सूची से शादी कैसे करें?

Nov 26 2020

Tldr संस्करण के लिए EDIT नीचे स्क्रॉल करें जहां यह कहता है कि मैं नीचे दिए गए कोड में बेहद करीब हूं।

मुसीबत

मेरे पास एक बुनियादी टूडू सूची है जो पूरी होने पर ये गुण होंगे:

  1. जब पृष्ठ लोड हो जाता है तो प्रपत्र फ़ील्ड फ़ोकस में होना चाहिए।
  2. जब उपयोगकर्ता ऊपर / नीचे तीर क्लिक करता है तो सूची में आइटम को सीएसएस पृष्ठभूमि रंग परिवर्तन के माध्यम से चुना जाना चाहिए।
  3. जब उपयोगकर्ता प्रपत्र में एक नया आइटम टाइप करता है तो उसे उपयोगकर्ता को सूची में दिखाई देना चाहिए।
  4. जब उपयोगकर्ता प्रपत्र फ़ील्ड में टाइप करता है, तो सूची में "त्वरित खोज" लागू होता है और केवल आइटम जो खोज से मेल खाते हैं। अन्य सभी सुविधाओं को अभी भी काम करना चाहिए। जब उपयोगकर्ता ऊपर / नीचे तीरों का उपयोग करके स्क्रॉल करता है, तो यह अभी भी काम करना चाहिए कि पृष्ठ पर कितने आइटम प्रदर्शित किए गए हैं। यदि केवल दो आइटम प्रदर्शित किए जाते हैं, तो उपयोगकर्ता को उन दो आइटम और फॉर्म फ़ील्ड फ़ोकस का चयन करने के लिए अप एरो का उपयोग करने में सक्षम होना चाहिए।

नंबर 4 को छोड़कर सभी आइटम ठीक काम करने लगते हैं। निम्न कोड 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)
}
 -->

मैं तत्काल खोज सुविधा के साथ उपरोक्त कोड से शादी करना चाहता हूं।

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)
}

मैंने अभी तक जो कुछ भी आजमाया है वह सिर्फ एक गड़बड़ करता है, सूची को वापस नहीं करता है और इनपुट क्षेत्र को चालू करता है।

कंसोल के नीचे का कोड.लॉग एक ऐसा सरणी है जो मुझे देता है जो मैं चाहता हूं कि उपयोगकर्ता खोजता है। अगला चरण इसे DOM पर लागू करना है। मैंने जो कुछ भी आजमाया है, वह काम नहीं किया है।

https://svelte.dev/repl/ceca685a3a4c49b4b5ccd780a101fc63?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 में दिखाई नहीं देता है। पर्दे के पीछे की हर चीज काम करती है। यह देखने के लिए कि मेरा क्या मतलब है, इनपुट फ़ील्ड में कोई आइटम जोड़ें, उसे सबमिट करें और फिर अक्षर को फॉर्म फ़ील्ड में टाइप करें और फिर बैक स्पेस बटन दबाएं। सूची फिर से दिखाई देगी।

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>




<!-- 


 -->

जवाब

William Nov 26 2020 at 22:53

मैं समझ गया। मैं एक प्रतिक्रियाशील सरणी के लिए क्लाइंट सरणी की एक प्रति सेट करता हूं। उम्मीद है कि यह किसी को बाहर करने में मदद करता है।

https://svelte.dev/repl/ad1c185bf97a47b98506c3603f510de6?version=3.30.0

<script>
    import { onMount } from 'svelte';
    let clients = ["a Little piggy","b little piggy","c little piggy"]; 
    $: 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>




<!-- 


 -->
SamGomena Nov 27 2020 at 03:14

यह आपके पास जो कुछ भी है, उससे थोड़ा अधिक रसीला संस्करण है, जो यहां एक गिस्ट में पाए गए कोड पर आधारित है । यह प्रभावी रूप से आपके समाधान के समान है (हालांकि एक अलग "फ़िल्टर्ड" सूची बनाना और प्रदर्शित करना)!

<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>