0
votes

I registered my views(html) and my viewModel(js) as knockout components. In my main file(index.html), I data-bind the components to show the different views. At this time when I want to quick debug a viewModel in the html with ko.toJSON($data, null,2), I need to add the data-bindin for ko.toJSON in everey html file which I want to debug. I would like to have a more generic way to do this like data-bind the ko.toJSON only in the main file(index-html) and pass the viewModel/$data?? to it.

//index.html
<body>

//here I want a generic way to debug my app like:
// <div data-bind="?">

    <div id="page" data-bind="component: {name: viewModel}"></div>
</body>

// components
ko.components.register('home', ko_home.init );
ko.components.register('import', ko_import.init );

//view
<main>
    <h1>home</h1>
     <div data-bind="text: greeting"></div>

// here I put the binding for debug in every view. It should be removed and //placed in the index.html
<pre data-bind="text: ko.toJson($data, null,2)"></pre>
</main>

//viewModel
const fs = require('fs');
const template = fs.readFileSync(__dirname + '/home.html', 'utf8');

function Home() {
    this.greeting = ko.observable('Hello');
}

exports.init = { viewModel: Home, template: template };
1

1 Answers

0
votes

I'd say the easiest way to go about including the debug element is to wrap your template with it when registering the component.

Since you already have an init object that holds the vm and template, you can re-assign the template property just before registering to add the <pre> html string.

For example:

var appendDebugPre = function(htmlString) {
  var pre = document.createElement("pre");
  pre.setAttribute(
    "data-bind", 
    "html: ko.toJS($data, null, 2)"
  );
  
  // Might be better to create a documentFragment,
  // but for debug purposes, this might be enough
  return htmlString + pre.outerHTML;
};

// Regular register:
var c = messageEditor();

ko.components.register(c.name, c.init);

// Register a debug version:
ko.components.register("debug-" + c.name, 
  Object.assign({}, c.init, {
    template: appendDebugPre(c.init.template) // Here, we wrap the template
  }));


ko.applyBindings({});


// Utils:
// From knockout docs, an example component:
function messageEditor() {
  return {
    name: 'message-editor',
    init: {
      viewModel: function(params) {
        this.text = ko.observable(params && params.initialText || '');
      },
      template: 'Message: <input data-bind="value: text" /> ' +
        '(length: <span data-bind="text: text().length"></span>)'
    }
  };
};

// Stub
ko.toJS = function(vm) {
  return JSON.stringify(
    Object.keys(vm).reduce(function(res, k) {
      res[k] = ko.unwrap(vm[k]);
      return res;
    }, {}), 
    null,
    2
  );
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

<div data-bind="component: 'message-editor'"></div>
<div data-bind="component: 'debug-message-editor'"></div>