htmlknockout.jsknockout-mvcknockout-binding-handlers

knockout toggle/expand the text on click of text


Binding data into html table using knockout. One of the column has large text 200 length.. and UI just got scroll long. So just want to show, first 20 length chars and click of, ... it should expand or collapse the text. so just created a template below,

 <script type="text/html" id="templateLongText">
        <span data-bind="text: (Comments.length > 20 ? Comments.substring(0, 20) + '<a href=\'#\' data-bind=\'click: toggle(Comments)\'>...</a>' : Comments)"></span>
    </script>

It does not work event, just rendering same text as above.

Edit: How toggle the expand or collapse text(Comments value) on click of ...


Solution

  • You could add a custom binding for this, which you can bind to any simple (observable) string. This custom binding:

    ko.bindingHandlers.expandText = {
      init: function(element, valueAccessor) {
        element.appendChild(document.createElement('span'));
        var toggle = document.createElement('a');
        toggle.appendChild(document.createTextNode("..."));
        toggle.href = "#";
        element.appendChild(toggle);
      },
      update: function(element, valueAccessor) {
        var text = ko.unwrap(valueAccessor());
        var textElement = element.getElementsByTagName('span')[0];
        var toggle = element.getElementsByTagName('a')[0];
        var collapsed = true;
        toggle.onclick = function() {
          collapsed = !collapsed;
          ko.utils.setTextContent(textElement, collapsed ? text.substr(0, 20) : text);
        }
        toggle.style.display = text.length > 20 ? 'inline' : 'none';
        ko.utils.setTextContent(textElement, collapsed ? text.substr(0, 20) : text);
      }
    };
    
    ko.applyBindings({
      sample1: '1234567890123456789012345',
      sample2: '123456789012345',
      sample3: '123456789012345678901234567890'
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <div data-bind="expandText: sample1"></div>
    <div data-bind="expandText: sample2"></div>
    <div data-bind="expandText: sample3"></div>