Search code examples
typescriptsvelte

Hide one element, and show another on the screen


I'm trying to implement a task for the Amazon Turk platform. In the task I need the participants to have a video which they should mark in several points, then when they press "submit" the video should change to the next one; in total we should have N videos, for example 10.

I thought of having a loop which will present a video from our source bassed on a logical indication array like showTask = [true, false, false, ...] when after the task is completed the true value will propagate to the next index (i.e., showTask = [false, true, false, ...]), untill the index is 9.

I have the updated code in this repo.

The relevant part I'm currently struggling with is:

App.svelte

<script lang="ts">
    import Captcha from "./components/Captcha.svelte";
    import ExampleGuidelines from "./components/ExampleGuidelines.svelte"
    import TrainingGuidelines from "./components/TrainingGuidelines.svelte"
    import TaskGuidelines from "./components/TaskGuidelines.svelte"
    import Consent from "./components/Consent.svelte";
    import Example from "./components/Example.svelte";
    import Training from "./components/Training.svelte";
    import Task from "./components/Task.svelte";

    let notRobot = false;
    let consentChecked = false;
    let showExample = true;
    let showTraining = true;
    let showTasks = false;
    const numberOfTasks = 10;
    let showNextTask = true;
    const imageDir = `https://raw.githubusercontent.com/lieldvd/mturk/main/15545`;
    let tasks = Array(numberOfTasks).fill({show: false});
    tasks[0].show = true; 

    function nextTask(currentIndex: number){
        tasks[currentIndex].show = false;
        if (currentIndex < numberOfTasks - 1){
            tasks[currentIndex+1].show = true;
        }
    }
    function startTraining(){
        showTraining = true
        showExample = false
    }
    function startTasks(){
        showTasks = true;
        showTraining = false;
    }
</script>

<main>
    {#if !consentChecked}
        <Consent on:agreed={() => (consentChecked = true)} />
    {:else if !notRobot}
        <Captcha on:notRobot={() => (notRobot = true)} />
    {:else}
         {#if showExample}
            <ExampleGuidelines />
            <Example on:startTraining={() => startTraining()}/>
        {:else if showTraining}
            <TrainingGuidelines />
            <Training on:startTasks={() => startTasks()}/>
        {:else if showTasks}
            <TaskGuidelines />
            {#each tasks as task, taskIdx}
                {#if task.show}
                    <h2>Task #{taskIdx}</h2>
                    <Task on:taskComplete={() => nextTask(taskIdx)}/>
                {/if}
            {/each}
        {/if}
    {/if}
</main>

specifically this function should change the presented item on screan:

function nextTask(currentIndex: number){
    tasks[currentIndex].show = false;
    if (currentIndex < numberOfTasks - 1){
        tasks[currentIndex+1].show = true;
    }
}

which should be rendered in this loop:

{#each tasks as task, taskIdx}
    {#if task.show}
    <h2>Task #{taskIdx}</h2>
        <Task on:taskComplete={() => nextTask(taskIdx)}/>
    {/if}
{/each}

and is should be done on the click of the button in Task component.

Task.svelte

<script lang="ts">
    import {createEventDispatcher} from "svelte";
    const dispatchEvent = createEventDispatcher();

</script>


<button on:click={()=>dispatchEvent("taskComplete")}>Next</button>

For now it doesn't work, and all the tasks are presented on one page as shown in the following image:

enter image description here


Solution

  • There should only ever be one task visible, right? Then swap the #each loop to a variable holding the currentIndex of the visible task

    <script>
        const tasks = Array.from({length: 10}, (_,index) => `Task ${index+1}`)
    
        let currentIndex = 0
        
        function nextTask() {
            if(currentIndex === tasks.length -1) {
                console.log('reached the end')
                return
            }
            currentIndex +=1
        }
    </script>
    
    <h1>{tasks[currentIndex]}!</h1>
    <button on:click={nextTask}>
      Next
    </button>
    
    <!-- <Task task={tasks[currentIndex]} on:taskComplete={nextTask} />-->