2

I have a table and I want to show it in two different ways. Different number of columns and position of its content and cells. I would like to provide users with a way to change from one to another view by just clicking a button.

I started doing it by just using the visible binding, but then I realized it was not the proper way of doing it as the content was just invisible but it was still being loaded in the DOM. I was duplicating content in the background and generating invalid HTML (duplicate id attributes in both tables, for example) and that was generating problems in the jQuery side.

Then I took a look at the use of knockout templates to accomplish it as in this example, and it solves my previous problems and it works, but using HTML inside <script> tags doesn't sound like the cleanest solution to me.

I'm not quite sure if the use of components can provide any solution for this cases, I wasn't able to find one.

Any suggestions about how to deal with this problem?

Alvaro
  • 40,778
  • 30
  • 164
  • 336

2 Answers2

4

Using knockout components + AMD is definitely what you're looking for. Take a look at this by Steve Sanderson, the author of knockout. It explains how to architect a SPA using ko with requirejs. It should clear your doubts

Example:

...
<div data-bind="component: myDynamicComponent"> </div>
...

Then, if you have your component loader configured to fetch its template & | or viewModel asynchronously you can have myDynamicComponent as an observable:

function RootViewModel(){
    var self = this;
    this.myDynamicComponent = ko.observable('some-component');

    this.someButtonClicked = function() { 
        self.myDynamicComponent('some-other-component'); // this should render your other component async (only if you configured your component loader to do so)
    }
}
Daniel Conde Marin
  • 7,588
  • 4
  • 35
  • 44
  • So I guess the way to emulate a dynamic template and load one or the another would be by using two components and setting the data to `null` or to the actual `data` depending on the one I want to show? – Alvaro Aug 12 '15 at 09:11
  • 1
    @Alvaro: I have edited my answer, I'll try to post a more complete example tonight – Daniel Conde Marin Aug 12 '15 at 09:18
  • Thanks a lot for it @Daniel, I believe I managed to get the same result as [this template example](http://jsfiddle.net/rniemeyer/Ujr4z/light/) in [this new fiddle](http://jsfiddle.net/Ujr4z/655/) by using components as you said. Let me know if there's something I did wrong or that it can be improved. – Alvaro Aug 12 '15 at 14:15
  • @Alvaro: Your fiddle is fine, but note you are still not asynchronously loading your components. However, using components is still cleaner there than using the template binding – Daniel Conde Marin Aug 12 '15 at 14:39
  • what do you mean regarding the asynchronous loading? The fact that I'm not using files for their templates? – Alvaro Aug 12 '15 at 15:23
  • @Alvaro: I mean fetching your templates (even your viewmodels) via ajax, or using AMD. Example 2 [here](http://knockoutjs.com/documentation/component-loaders.html) shows a way of doing it using jquery ajax. – Daniel Conde Marin Aug 12 '15 at 15:34
1

Templates inside script tags are superseded by template tags. You might look at this recent answer I wrote for an example.

Update: Not all the Knockout component documentation has been updated, but it is here.

Another option is dynamically loading templates via AMD (require.js).

Community
  • 1
  • 1
Roy J
  • 42,522
  • 10
  • 78
  • 102