What is the best way to toggle each div individually in a knockout foreach without requiring additional HTML?

In order to create a treeview, I utilized the foreach method to generate markup for each item in an observable array.

Here is an example output:

Category Name 1 Content Content Category Name 2 Content Content

My issue arises when clicking on a category name - instead of toggling just its content, all categories are currently being shown/hidden.

 var reportFilters = [
        { Text: "Campaign", Value: primaryCategories.Campaign },
        { Text: "Team", Value: primaryCategories.Team },
        { Text: "Agent", Value: primaryCategories.Agent },
        { Text: "List", Value: primaryCategories.List },
        { Text: "Inbound", Value: primaryCategories.Inbound },
        { Text: "Daily", Value: primaryCategories.Daily },
        { Text: "Services", Value: primaryCategories.Services },
        { Text: "Occupancy", Value: primaryCategories.Occupancy },
        { Text: "Data", Value: primaryCategories.Data }
    ];


  self.showCategory = ko.observable(false);      
    self.toggleVisibility = function (report) {
        var categoryName = report.PrimaryReportCategory;
        var categoryContent = report.ID;
        if (categoryName == categoryContent ) {
            self.showCategory(!self.showCategory());
        };
    }
  <div class="report-category-treeview"  data-bind="foreach: $root.categories, mCustomScrollBar:true">
            <ul class="column-list" >
                <li class="report-category-heading" data-bind="click: $root.toggleVisibility"><span class="margin-top10" ><i class="fas fa-chevron-down"></i> <span class="report-category-name" data-bind="text: categoryName"></span></span></li>
                <li id="panel" class="report-category-container" data-bind="foreach: reports, visible: $root.showCategory">
                    <div class="column-list-item" data-bind="click: $root.report_click, css: { 'selected': typeof $root.selectedReport() != 'undefined' && $data == $root.selectedReport() }">
                        <span class="column-list-text" data-bind="text: ReportName"></span>
                    </div>
                </li>
            </ul>
        </div>

Answer №1

At the moment, every time I select a category name, it causes all categories to either appear or disappear.

This happens because the observable showCategory is in charge of toggling the visibility for all categories. What you actually need is an individual show/hide toggle for each category.

Although I don't have the complete data model, based on your question regarding categories, you should consider creating a separate view model for category, along with a container view model referred to as master:

var categoryVM = function (name) {
    var self = this;
    self.name = ko.observable(name);
    self.isVisible = ko.observable(false);
    self.toggleVisibility = function () {
        self.isVisible(!self.isVisible());
    }
    // ... add any other necessary observables here ...
}

// You can name 'masterVM' whatever you prefer
var masterVM = function () {
    var self = this;
    self.categories = ko.observables([]);
    // ... feel free to include additional observables like 'reports' ...
    self.init = function (rawCategories) {
        rawCategories.forEach(function (item) {
            categories.push(new categoryVM(item.name)); // make sure to replace 'name' with the appropriate property
        }
    }
}

var master = new masterVM();
master.init(getCategories()); // provide the categories from your data source
ko.applyBindings(master);

In your HTML markup, your outer foreach could look like this:

<div class="report-category-treeview" data-bind="foreach: categories ... />

And your list items (li) - without nested tags for brevity - would be structured as follows:

<li class="report-category-heading" 
    data-bind="click: toggleVisibility">
<li id="panel" class="report-category-container" 
    data-bind="foreach: $root.reports, visible: isVisible">

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

angular ensuring seamless synchronization of objects across the application

This question pertains to both angular and javascript. In our angular app, we have numerous objects from the backend that need to remain synchronized. I am facing challenges in establishing efficient data bindings to ensure this synchronization throughout ...

The NPM Install process seems to be skipping certain files that were successfully installed in the past

When I first installed NPM Install in a folder, it created multiple folders and files: node_modules public src .DS_Store package.json package-lock.json webpack.config.js After that, npm start functioned perfectly. Now, as I embark on a new project for th ...

Issue with grunt-closure-tools: ERROR - There is a parse error due to using a reserved word as an

Currently, I am utilizing the "grunt-closure-tools" tool. Initially, minifying a simple JS file was successful without any issues. However, encountering an exception arose when attempting to minify either the AngularJS or Bootstrap libraries: Error: Comm ...

Creating a dynamic variable within a for loop and calculating the total of values to assign to that variable

Is it possible to dynamically create variables and add values to them repeatedly? For example: var totalIncomeCr = 0, totalIncomeDr = 0; for (var k = 1; k <= numOfYears; k++) { if(response[i]["AmountType" + k] == "Cr") { if(response[ ...

Updating ngModel value dynamically from controller

I have been trying to update the value of an ngModel variable from my controller, but it doesn't seem to be reflecting in the views. Despite looking at other solutions on SO, nothing has worked for me so far. I am looking for a solution that doesn&apo ...

react - Arrow body should not be enclosed in a block statement

I am working with an array const reportOptions = [ { id: 1, title: 'Report', }, { id: 2, title: 'Report 2', }, { id: 3, title: 'Report 3', }, ] My goal is to create a new state as shown be ...

Unique ActionBar design for my NativeScript-Vue application

I'm currently working on customizing the ActionBar for my nativescript-vue app. I have implemented FlexBoxLayout within the ActionBar, but I am facing an issue where the icon and title of the bar are not aligning to the left as intended; instead, they ...

Searching with RegEx results in a negative value, despite the fact that the specified phrase is clearly within the array

When importing an excel file into Angular using the xlsx library, the file is converted into an object of arrays. Each array represents a row from the excel file, and each item within the array corresponds to a cell in that row. The process for importing t ...

tips for utilizing namespaced getter filtering within a Vuex module in vueJs

In my custom module named ShopItemCategory, I have a Getter getters: { shopItemsCategories: state => state.ShopItemsCategories.data, }, Inside the component, there is a computed function I defined computed: { shopItemsCategories ...

Resolve the problem with storing data in a foreach loop using PHP sessions

Imagine I have a form that sends out data. Let's say it sends out the following information: Age => 23 Gender => Male Country => UK Now, my goal is to save this data in an existing session array. This array already has mor ...

Finding a way to extract a singular text node after the Span element but before the br tag using Selenium WebDriver

I am trying to retrieve the text between span and br tags. In the HTML snippet below, I am aiming to extract the Orange text: <td role="grid cell"> <span class="ui-column-title">Fruits</span> <span id="all fruits"> "Orange" < ...

CSS media query to target specific viewport width

In my JavaScript code, I am dynamically creating a meta viewport. I set the value of this viewport to be 980px using the following script: var customViewPort=document.createElement('meta'); customViewPort.id="viewport"; customViewPort.name = "vie ...

Netbeans encountering issues with AJAX functionality

Currently studying AJAX in my class and encountered an issue while attempting to make AJAX function. The specific problem I am facing is that the onKeyUp event of an HTML text box does not trigger any JavaScript function when running the file through Netbe ...

What is the quickest method to display the current year using Node.js?

Is there a way to efficiently print the current year in Node.js? I need to display the current year in the footer along with the Copyright notice. I know that using JavaScript works: <script type="text/javascript">document.write(new Date().getFullY ...

Variations in how arrays are declared in Swift

When it comes to declaring in Swift, what sets apart var list = NSMutableArray() from var list:NSMutableArray = []? ...

unable to configure socket.io to start listening on IPv4 address

While setting up IPV4 in Socket.IO, I encountered the following error: /var/www/js/AndroRAT/node_modules/socket.io/lib/index.js:279 opts.path = opts.path || this.path(); ^ TypeError: Cannot create property 'path' on string '0.0.0 ...

I'm having trouble using the $max field update operator in Mongoose. Can anyone offer any suggestions or advice?

I'm currently exploring the $max update operator in Node.js with Mongoose for a project. However, I seem to be encountering issues either due to my implementation error or because Mongoose does not support this feature. (Here's a snippet of what ...

Open up the index.html page whenever the page is refreshed

Currently, I am utilizing the fullPage.js plugin to enable page-by-page scrolling. This plugin utilizes hash URLs for navigation. However, upon refreshing the page, it always loads at the last visited hash URL. Is there a way to ensure the document loads a ...

The CSP header is configured incorrectly, please correct it

Having trouble with my website's JavaScript. The dropdown box in Bootstrap isn't working on the main page, but works fine in a sub-directory. My CSP header is: script-src 'self' //ajax.cloudflare.com According to the CSP documentation ...

Employing jQuery Validate to emphasize the label when it is deemed invalid

(TLDR: Check out my update towards the end) Utilizing jQuery Validate, I've successfully set up and configured the validation feature. However, I'm facing an issue with highlighting the label of radio buttons in red when no option has been selec ...