This took me way to long and I still think my implementation is rather bad and confusing, right now I’m just largely confused why things break if I remove checkedActivities.has(activity) ? "checked" : "unchecked"
because I thought my typescript replaces this functionality. Any advice would be greatly appreceated.
<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>
2
Answers
i am trying to make your example working ts-example
You should not query the DOM or modify it directly like that. All the code adding/removing classes manually should be removed.
The main issue is that
checkedActivities
is mutated without assignment, which does not trigger updates of anything that depends on it.The toggle function should be reduceable to:
Any class changes should happen in markup using the
class
attribute or aclass:...
directive.