Tips for implementing a method to switch CSS properties of a main container by using a checkbox within its child element in a Svelte component

It took me a while to figure this out, but I still feel like my implementation is not ideal. I'm confused as to why things break when I remove the

checkedActivities.has(activity) ? "checked" : "unchecked"
, because I thought TypeScript was supposed to handle this functionality. Any advice on this would be greatly appreciated.

<script context="module" lang="ts">
    import userActivities from "../userActivities.json";
    const activityArray: string[] = userActivities.activities.map(
        ([name, icon]) => name
    );
    export let selectedActivities: String[] = activityArray.slice(0, 3);

    let checkedActivities = new Set(activityArray.slice(0, 3));
    function toggleActivitySelection(activity: string) {
        let div = document.getElementById(activity);
        if (checkedActivities.has(activity)) {
            checkedActivities.delete(activity);
            div?.classList.remove("checked");
            div?.classList.add("unchecked");
        } else {
            checkedActivities.add(activity);
            div?.classList.remove("unchecked");
            div?.classList.add("checked");
        }
        console.log(checkedActivities);
    }
</script>

<div>
    <div class="heading-bar">
        <span>Saved activities</span>
        <form action="/activities">
            <button on:click={() => console.log(selectedActivities)}
                >Done</button
            >
        </form>
    </div>
    <div class="bg-container">
        {#each activityArray as activity}
            <div
                class={checkedActivities.has(activity) ? "checked" : "unchecked"}
                id={activity}
            >
                <label>
                    <input
                        class="input_checkbox"
                        id="input_checkbox"
                        type="checkbox"
                        bind:group={selectedActivities}
                        value={activity}
                        on:change={() => {
                            toggleActivitySelection(activity);
                        }}
                    />
                    {activity}
                </label>
            </div>
        {/each}
    </div>
</div>

<style>
    input[type="checkbox"] {
        width: 100%;
        height: 100%;
        display: none;
    }

    label {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    div.checked:hover, div.unchecked:hover {
        border-left: 2px solid var(--color-text) !important;
        border-bottom: 2px solid var(--color-objects) !important;
        border-right: 2px solid var(--color-text) !important;
        border-top: 2px solid var(--color-objects) !important;
    } 

    div.checked {
        padding-top: 0.5em;
        padding-bottom: 0.5em;
        border-radius: 20px;
        margin: 0.5em 0;
        border-left: 2px solid var(--color-text) !important;
        border-bottom: 2px solid var(--color-objects) !important;
        border-right: 2px solid var(--color-text) !important;
        border-top: 2px solid var(--color-objects) !important;
    }

    div.unchecked {
        padding-top: 0.5em;
        padding-bottom: 0.5em;
        border-radius: 20px;
        margin: 0.5em 0;
        border-left: 2px solid var(--color-objects) !important;
        border-bottom: 2px solid var(--color-objects) !important;
        border-right: 2px solid var(--color-objects) !important;
        border-top: 2px solid var(--color-objects) !important;
    }

    .heading-bar {
        display: flex;
        justify-content: space-between;
        align-items: baseline;
        margin-top: 1.8em;
        margin-bottom: 0.6em;
    }

    .bg-container {
        border-radius: 12px;
        background-color: var(--color-objects);
        padding: 1em 1.4em;
    }

    #item {
        display: flex;
        align-items: center;
        justify-content: center;
    }

    button {
        background-color: var(--color-objects);
        border: none;
        color: var(--color-text);
        font-size: 1em;
        border-radius: 10px;
        padding: 0.5em 0.5em;
    }
</style>

Answer №1

It is not recommended to directly manipulate the DOM by querying or modifying it. Manually adding or removing classes in the code should be avoided.

The main problem lies in the fact that checkedActivities is being altered without proper assignment, which fails to trigger updates for any dependent elements.

The toggle function can be simplified to:

function toggleActivitySelection(activity: string) {
    checkedActivities.has(activity) ?
        checkedActivities.delete(activity) :
        checkedActivities.add(activity);

   checkedActivities = checkedActivities; // ensures updates are triggered
}

For changing classes, it is advised to use markup with the class attribute or a class:... directive.

Answer №2

i'm currently experimenting with your sample code ts-example

<script lang="ts">
    const userActivities = {activities:[
      {name:"name1",icon:"icon",checked:false},  
      {name:"name2",icon:"icon",checked:false},
      {name:"name3",icon:"icon",checked:false} 
    ]}
  let selectedActivities:any
</script>

<div>
    <div class="heading-bar">
        <span>Saved activities</span>
        <form action="/activities">
            <button on:click={() => console.log(selectedActivities)}
                >Done</button
            >
        </form>
    </div>
    <div class="bg-container">
        {#each  userActivities.activities as i}
            <div
                class={i.checked ? "checked" : "unchecked"}gt;
                <label> {i.name} 
                  <input type="checkbox" bind:checked={i.checked} on:change={_ = >selectedActivities = i} />
                </label>
               
            </div>
        {/each}
    </div>
</div>

<style>
    input[type="checkbox"] {
        width: 100%;
        height: 100%;
        /* display: none; */
    }

    label {
        width: 100%;
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    div.checked:hover, div.unchecked:hover {
        border-left: 2px solid var(--color-text) !important;
        border-bottom: 2px solid var(--color-objects) !important;
        border-right: 2px solid var(--color-text) !important;
        border-top: 2px solid var(--color-objects) !important;
    } 

    div.checked {
      color: green;
    
    }

    div.unchecked {
     color:red;
    }

   


</style>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Coloring intersected meshes in three.js will recolor every mesh in the scene

My attempt to change the color of a mesh on mouse hover is not functioning as expected. Instead of coloring only one mesh red, every single mesh is being filled with the color. Upon inspecting the intersected objects during debugging, it shows only one el ...

Trouble with Background Image Display in Internet Explorer 8

I have been attempting to set a background image for the . element, but it is not displaying correctly. The image shows up in Firefox and Chrome, but not in Internet Explorer. I have included a link to my website and relevant CSS code below. Can anyone pro ...

Troubleshooting problem with CSS hover effect on background images

Can anyone assist me with creating a simple mouse hover effect on these two images? I am having trouble getting it to work. I am looking for a fade transition to occur when the mouse is over the images. Thank you in advance! * { padding: 0; margin: ...

Has the default underline in Bootstrap 5 been altered?

When working with Bootstrap 4, I noticed that it sets the default text-decoration to be none. However, in Bootstrap 5, just adding a regular anchor tag results in both blue text and an underline being displayed. I was trying to achieve only showing the u ...

Restrict page scrolling to the vertical position of a specified div [Using jQuery, javascript, and HTML]

Currently, I am in the process of developing a personal website that features numerous expandable items. My goal is to restrict the page scrolling to the height of the expanded item once it is opened. I do not want users to be able to scroll above or below ...

Using cascading style sheets to switch a page into editing mode

Is it possible to change the view of a page after clicking a button without using javascript, and instead relying solely on CSS? I want to display a page with information where users can click an edit button and make changes within the same view rather th ...

Record the variable as star symbols in the VSTS Extension

I am working on a VSTS extension using Typescript and utilizing the vsts-task-lib Currently, I am encountering an issue with the execSync function, which displays the command being executed. However, I need to hide a token obtained from a service by displ ...

The HTML checkbox is initialized as checked when the page loads

Is there a way to set the checkbox as unchecked in HTML? I have tried multiple ways, but it always loads as checked <input id="chkBox" checked type="checkbox" /> <input id="chkBox" checked=false type="checkbox" /> <input id="chkBox" checked ...

Template specific requirements in Angular

When I have a child component app-page-header, here's what I want to achieve: If the value of headerOptions.headerTitle is not 'Idle Disposition', then set [titleData] to equal 'headerOptions.headerTitle'. However, if headerOptions ...

How do I eliminate excess space following the resizing of the Material UI Drawer component?

I adjusted the size of my MUI drawer to a specific width and now I am facing an issue where there is extra space left after resizing. This results in a margin-like space between the drawer and the Lorem Ipsum text content. My goal is to eliminate this rema ...

The connection between an HTML form and PHP is not being established

variable-passing.php `<form method="post" action="variable-catching.php"> <input type="text" name="name1"/><br/> <input type="text" name="name2"/><br/> <input type="text" name="name3"/><br/> <input type="te ...

Issue with HTML CSS: There is a gap between the words "Get" and "started", causing "get" to appear on

Greetings, it appears I am encountering an issue with my website. When I refer to "Get Started," it displays as "GetStarted." However, when I insert a space between "Get" and "started," it separates onto two lines as "Get" on the first line and "started" o ...

The issue with ng-bind-html causing the disappearance of paragraph spaces

Is there a way to preserve paragraph breaks when using ng-bind-html to display text on the screen? I am having an issue where all the text appears as one big chunk if there are paragraph breaks in the data pulled from the database. Not sure what is causing ...

Struggling with consolidating values in an array of objects - seeking assistance with Javascript

Currently, I am handling a project where I receive data in the form of an Object Array. My task is to merge values with the same key into one key and convert the values into an array of strings. Below is the sample data I am working with: inputArray = [ ...

Utilizing the data sent to a modal to enhance the functionality of the code by combining it with the src attribute of an <embed> element

I am trying to pass a dynamic string of data to a Bootstrap modal using the data-val attribute in an HTML table. <td <button type="button" class="btn btn-success btn-xs" data-val="<?php echo $row['order_id']; ?&g ...

Is it possible to define data types for the global context in cucumber?

Embarking on a fresh cucumber-selenium project in Typescript, I am eager to keep the Driver in the world context. However, following the method suggested here, I encounter an issue where the Driver type remains inaccessible to step definitions. This means ...

Arranging content within a bounding box

Hello everyone, I'm currently working on creating a webpage layout with a main container that will house all the content. Inside this container, I have an image covering a specific portion of it, a title positioned to the left, and text to the right. ...

Searching for specific values within data attributes using jQuery wildcards

I am currently utilizing the data_attribute on this page and have the following elements with data attributes. No. 1.<div class="row hidden" data-party-registration-source-type-id="1"> 2.<div class="row hidden" data-party-registration-source- ...

What is the best way to customize the lower border color of a collapsed Bootstrap navbar with an inverse design

Discussing this issue.. I am noticing two distinct colors. One is darker than the background shade and the other is lighter than the background shade. How can these be set? <nav class="navbar navbar-inverse"> <div class="container-fluid"> ...

Tips for enhancing the responsiveness of a calendar table in Bootstrap 5.2

Hello there! I need some help with adding rounded borders to tables using Bootstrap. Can anyone assist me with this? I'd be truly grateful for any guidance on this matter. Unfortunately, Stack Overflow is not allowing me to post my question, so I&apos ...