Is it possible to hide the <dd> elements within a <dl> using knockout's custom data binding upon initialization?

I have implemented a <dl> where the <dd> can be expanded/collapsed by clicking on the corresponding <dt> using knockout's data binding. The inspiration for my solution came from a tutorial on creating custom bindings.

Currently, I have successfully set up everything to toggle the visibility of all elements when clicking on a <dt>. However, my intention was to initially hide all the <dd> elements but I am facing difficulty accomplishing this.

Here is a simplified example illustrating the issue:

HTML:

<dl data-bind="foreach: items">
    <dt data-bind="click: toggleDefinition">DT: Lorem ipsum</dt>
    <dd data-bind="slideVisible: definitionVisible, slideDuration: 300">DD: dolor sit amet</dd>    
</dl>

JavaScript:

ko.bindingHandlers.slideVisible = {
    init: function (element, valueAccessor) {
        var value = ko.unwrap(valueAccessor());
        $(element).toggle(value);
    },
    update: function (element, valueAccessor, allBindings) {
        var value = ko.unwrap(valueAccessor());
        var duration = allBindings.get('slideDuration') || 400;
        if (value) {
            $(element).slideUp(duration);
        } else {
            $(element).slideDown(duration);
        }
    }
};

var model = function(){
    var self = this;
    self.items = ko.observableArray([
        new item(),
        new item(),
        new item()
    ]);
};

var item = function(){
    var self = this;
    self.definitionVisible = ko.observable(false);
    self.toggleDefinition = function (e)
    {
        self.definitionVisible(!self.definitionVisible());
    };
};

ko.applyBindings(new model());

What I have attempted so far:

Trying to hide the <dd> elements using CSS did not work as expected (no noticeable difference):

dd {
    display: none;
}

Setting the property to true partially worked - it hides the <dd> elements but reveals them with an animation which is not desired:

self.definitionVisible = ko.observable(true);

I have also created a working demo on jsfiddle

Do you have any suggestions on what else I could try or change to keep the <dd> elements hidden until a <dt> is clicked?

I am puzzled why the update function gets triggered, making the items visible again. I have been trying to determine the cause, but the call stack provided by knockout does not offer much help.

Answer №1

The update function is activating correctly as outlined in the documentation:

Knockout will execute the update callback initially when applying the binding to an element and monitor any dependencies (observables/computeds) that are accessed

In addition, your handler isn't functioning because certain scenarios were overlooked in your logic: instead of basing show/hide actions solely on the current value, you should consider the following conditions:

  • If the element is currently hidden and the new value of definitionVisible is true -> display the element
  • If the element is currently visible and the new value of definitionVisible is false -> hide the element

Adapting this to your code snippet:

update: function (element, valueAccessor, allBindings) {
    var value = ko.unwrap(valueAccessor());
    var duration = allBindings.get('slideDuration') || 400;
    if ($(element).css('display') != 'none' && !value) {
        $(element).slideUp(duration);
    }
    if ($(element).css('display') == 'none' && value) {
        $(element).slideDown(duration);
    }
}

Check out the demonstration on JSFiddle.

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

Callbacks in Laika tests go untriggered

Meteor.collection.insert() allows for the use of a callback as one of its arguments. To demonstrate, you can start a new Meteor project and execute the following code in the browser's console. my_collection = new Meteor.Collection("myCollection"); my ...

Pressing the submit button in the Material UI table clears all selected checkboxes

Take a look at this code snippet: https://jsfiddle.net/aewhatley/Lkuaeqdr/1/. My objective is to construct a table with a submit button utilizing Material-UI components. const { Table, TableHeader, TableHeaderColumn, TableBody, TableRow, Table ...

What is the best way to showcase information from multiple JSON files simultaneously?

Creating dynamic JSON URLs based on browser cookie data. var cookie = $.cookie('faved_posts'); The cookie contains IDs like 123456, 111111, 000001, etc. Now we need to request the JSON file for each ID in the cookie. We have: $.each(cookie, ...

transmit data retrieved from `getStaticProps` to other static pages in NextJS

While working on my project, I encountered the task of fetching a large JSON dataset from an external API within the getStaticProps function. This dataset needs to be divided into multiple parts and passed as props to numerous static pages (potentially hun ...

Using jQuery to modify the CSS of a div located outside of an iframe

Currently, I am developing a straightforward script. Firstly, here is all of the code that I have: <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script type="text/javascript"> function SuperWebF1() { $("#outerd ...

How can you override the selected classes for menu items in Material-UI using React.js?

Hey there! I'm facing an issue where I can't override the class that displays the correct styling when a menuItem is selected. Below is my code: <MenuItem component={Link} to="/Acceuil" className={{root:classes.menuItem ,selected:cla ...

Generating examples of two models that are interdependent

In my Javascript form, I have implemented an AJAX POST request that successfully creates a new instance of a model called Component. Now, my goal is to allow users to input keywords for the Component model through the same form. To achieve this, I have al ...

Struggling with applying mixins

Is it possible to select only the top border using this mixin? Currently, I only need a top border but would like to have the option to use others in the future. Using separate mixins for each side of the border seems inefficient. .bordered(@top-width: 1 ...

Encountered an error while parsing a module in React: Unexpected token

After deciding to incorporate the npm package react-radio-buttons into my project, I encountered an error upon installation and implementation in my component: ./node_modules/react-radio-buttons/index.jsx 80:6 module parse failed: Unexpected token (80:6) ...

Redirect with Jquery immediately after the session expires

I am developing a website using ASP.NET MVC and I would like the system to automatically redirect users to the login page after their session has timed out, similar to how Gmail handles it. Currently, I have set up Ajax calls to the controller to check th ...

What is the best way to retrieve scope variables from multiple directives?

I am working on a directive that represents a person with changing location attributes. My goal is to access all the locations together and plot them on a map using the angular-leaflet-directive. I'm struggling to figure out how to access these variab ...

Is node.js required for utilizing Angularjs?

Considering incorporating angular.js into my website's Image Editing Tool. Is node.js necessary for this integration? I'm a bit puzzled here. Are there instances where both nodejs and angularjs are used together, or can they operate independentl ...

What's the best way to add line numbers to source code on an HTML webpage after parsing?

I am currently working with AngularJS and MongoDB. In my MongoDB data, there are some text elements that contain a \n, causing each line to be displayed on a new line based on the occurrence of \n. However, I also want to add line numbers to each ...

Issues with Css custom properties on certain webhosting platforms

Seeking assistance with a CSS custom properties issue. Recently purchased a web hosting service from Hostinger and using the default Wordpress template. Our web designer created a website in teleporthq.io, exported the files as HTML and CSS. Deleted the ...

How do I resolve the issue of unable to align the element correctly?

I am struggling to create a hamburger menu icon and align it using flexbox. Unfortunately, the icon is not aligning properly as it is going beyond the menu and the browser screen with an odd top indent. Below is the code I have written: * { margin: 0 ...

Retrieving the initial item from a Response.Json() object

i have a this code: fetch("https://rickandmortyapi.com/api/character/?name=Rick") .then((response) => { response.json().then((data) => { console.log(JSON.stringify(data)) }).catch( (error) => { console.log(`Error: $ ...

Using Node's Express bodyParser() to access a JSON string that has been parsed

Question: How can I retrieve the parsed JSON object from the server side? I have successfully sent a JSON string to the server, but I am having trouble accessing the object once it is parsed. The client-side script for sending the JSON data is as follows ...

Utilizing a function from a library in an Object within a Typescript environment

Currently, I am working on assigning a field within my interface to a function from an external library in the following manner: import { Accelerometer, } from 'expo-sensors'; type SensorInterface = { permChecker: () => Promise<Permiss ...

Encountering issues with Vue 2.5 dynamic dropdown clicks not working as expected

Creating a dynamic dropdown with Vue.js 2.5 A static dropdown menu example: <ul class="dropdown-menu" role="menu" id="dropdown"> <li><a href="#" v-on:click="setDate('2018-11-11')">2018-11-11</a></li> <li> ...

Exploring the documentation of node.js with doxygen

When it comes to my C projects, I make sure to document them using Doxygen. Recently, I delved into the world of NodeJs and attempted to document .js files with Doxygen, but unfortunately, no output was generated. Despite my efforts to search for answers ...