Implementing Bootstrap 4 accordions within a Knockout foreach loop, adjusting the icon upon expansion/collapse dilemma

I have a collection of collapsible sections within a main collapsible section like:

<div id="parentAccordion" class="card-accordion">
        <div class="card">
            <div class="card-header bg-black text-white pointer-cursor">
                <div class="row">
                    <div style="font-size:16px">Custom - <span data-bind="text:$root.nameSelected"></span></div>
                </div>
            </div>
            <div id="parentBody" class="collapse show" data-parent="#parentAccordion" style="background-color: #d9e0e7">
                <!-- begin #accordion -->
                <div id="oAccordion" class="card-accordion">
                    <!-- begin card -->
                    <div class="card" data-bind="foreach:$root.fbolist">
                        <div style="padding: 3px">
                            <div class="card-header bg-black text-white pointer-cursor" data-toggle="collapse" data-bind="attr: { href: '#O'+CourseId(), title: cName }">
                                <i class="fa fa-caret-right"></i>
                                <span data-bind="text:cName">NAME</span>
                            </div>
                            <div class="collapse" data-bind="attr:{'id':'O'+CourseId()}" data-parent="#oBody">
                                <div class="card-body white text-justify">
                                    <!-- content here -->
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

Now, I'm attempting to change the icon when an item is expanded to caret-down and back to caret-right when collapsed. Only one collapsible item from the child list (fbolist) should be open at a time, closing the others. I've utilized this JavaScript code to switch the icons:

$('.collapse').on('shown.bs.collapse', function () {
$(this).parent().find(".fa-caret-right").removeClass("fa-caret-right").addClass("fa-caret-down");
}).on('hidden.bs.collapse', function () {
    $(this).parent().find(".fa-caret-down").removeClass("fa-caret-down").addClass("fa-caret-right");
});

However, it changes all the icons for the remaining collapsible items inside Knockout foreach. Is there a method to avoid changing all icons to caret-down when only one is expanded? It should display the caret-down icon only on the opened item, with the rest showing caret-right.

Answer №1

To specifically target the collapsing/expanding element, you have the option to create a custom binding handler:

ko.bindingHandlers['collapse'] = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        $(element).on('shown.bs.collapse', function () {
            $(element).parent().find(".fa-caret-right").removeClass("fa-caret-right").addClass("fa-caret-down");
        }).on('hidden.bs.collapse', function () {
            $(element).parent().find(".fa-caret-down").removeClass("fa-caret-down").addClass("fa-caret-right");
        });
    }
};

You can then use this custom handler on elements with the collapse class.

<div class="collapse" data-bind="attr:{'id':'O'+CourseId()}, collapse" data-parent="#oBody">
    <div class="card-body white text-justify">
        <!-- content goes here -->
    </div>
</div>

Answer №2

$('.collapse').click(function() {
    $(this).find(".pointer-cursor").removeClass("fa-caret-right").addClass("fa-caret-down");
    $(this).parents(".card").siblings().find(".fa-caret-down").attr("class", " fas fa-caret-right");
});

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

When using Mongoose's save function within an async.each loop, it may

While working on an array processing task that involves saving and validating data asynchronously, I encountered an issue with duplicates. Here is the data I'm currently processing: var guests = [{ "email": "<a href="/cdn-cgi/l/email-protection" ...

Locate a specific sequence of characters within an array of objects using JavaScript

I am working with an array of objects, where each object contains a string value. My task is to search for a specific substring within the string. [ { "link": "https://www.sec.gov/Archives/edgar/data/1702510/000170251022000084/00 ...

Overlapping of JavaScript Array.push() function within nested arrays causing duplication

Recently, I encountered a puzzling situation while attempting to create arrays with three levels of depth. It may seem crazy, but this approach was the most suitable solution to my problem at the time. The code snippet below illustrates how these nested ar ...

Can IE Conditional Comments have a negative impact on page speed?

Debates between "CSS hacks" and "Conditional Comments" have become a regular occurrence for me lately, so I wanted to hear the thoughts of the Stack Overflow community on this topic. <!--[if IE]> <link type="text/css" rel="stylesheet" href="ie-s ...

Animate owlCarousel slide motion in reverse when using the Prev and Next buttons

The default functionality of owlCarousel is to move to the right when clicking Next and to the left when clicking Prev. However, after applying animations, both directions always move in the same direction. Check out this sample on jsfiddle to see the iss ...

Error: Trying to access property '1' of an undefined value is not allowed

I'm experiencing a problem that I can't seem to solve. The issue arises after the user logs in. I am using useEffect() to retrieve the user data by using a secret token from localstorage. Everything seems to be working fine - the data, the secret ...

"Encountering a RangeError with Node.js Sequelize while working with

I need some assistance with using Sequelize in my Node.js application paired with MySQL. When I try to execute the command npx sequelize db:create, I encounter an error that I do not know how to resolve. Any guidance on this matter would be greatly appreci ...

Is it possible to find a more efficient approach than calling setState just once within useEffect?

In my react application, I find myself using this particular pattern frequently: export default function Profile() { const [username, setUsername] = React.useState<string | null>(null); React.useEffect(()=>{ fetch(`/api/userprofil ...

Error Uploading File to Cloudinary Platform

I am currently developing a REST API using Express.js. The main functionality of the API involves accepting a video file from the client and uploading it to Cloudinary. Interestingly, when I test the API by returning the file back to the client, everything ...

Converting Apache POI Word documents to clean HTML stripping out styles and superfluous tags

I am currently working on converting Word documents to clean HTML. I have been using Apache POI, but it seems to create messy output similar to MS Word's own HTML saving method. What I really need is a solution like the one offered by . For instance, ...

Tips for merging ajax div elements

Here's a combination of my Ajax scripts, integrating the first and second versions: 1st <script> function Ajax() { var xmlhttp; if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp ...

Disabling a jQuery function on an external page: Step-by-step guide

I have encountered a challenge while trying to load an anchor tag on an external page using a specific method: <a href="page.html#div> This method is meant to link me to another page's particular div. <div name="div"> stuff </> H ...

Checking for an empty value with javascript: A step-by-step guide

Below is an HTML code snippet for checking for empty or null values in a text field: function myFormValidation() { alert("Hello"); var name = document.getElementById("name").value; alert(name); if (name == null || name == "") { document.ge ...

The appended button remains unresponsive when clicked

After conducting extensive research, I have come across numerous questions on overflow regarding a specific issue, but none of the solutions seem to work. The problem revolves around a button that appears on the page when another element is clicked. The u ...

Interacting with PHP through JavaScript function calls

I am facing some frustration with my website due to an issue involving PHP. When I retrieve data from a PHP file, it returns a JSON list like this: {"Data":{"Recipes":{"Recipe_5":{"ID":"5","TITLE":"Spaghetti Bolognese"},"Recipe_7":{"ID":"7","TITLE":"Wurst ...

Is it possible to utilize the HTML5 browser storage on multiple domains simultaneously?

When considering options for HTML5 browser storage such as IndexedDB or Web Storage, it's important to note that the "same origin policy" applies based on what is stated in the specification. Is there a method to store data within the browser that ca ...

Adding query strings to the end of a URL in order to redirect to a new destination

After successfully capturing a query string at the start of my survey with PHP syntax, I now have it stored in a variable. My next challenge is to redirect to a different URL at the end of the survey, while also including that same query string. For insta ...

Error: The value is null and cannot be read

My external application is set up within a const called setupRemote, where it starts with the appConfig in the variable allowAppInstance. export const setupRemote = () => { if (isRemoteAvailable) { try { ... const allowAppInstance = S ...

Is it possible to extract around 10 variables from a JavaScript code, then display them on a webpage after execution?

I have just completed writing a Javascript code with around 3,000 lines. This code contains over 60 variables, but there are a few specific variables that I would like to display on my main HTML page. These variables include: totalTime longitudinalAcceler ...

Guide on verifying Unicode input in JavaScript?

I am looking to create a form where the user can only input Khmer characters (Unicode characters) and display an alert if they input anything else. Khmer Name: <input type="text" class="namekh" name="namekh"> To achieve this, here is a snippet of m ...