0
votes

How can i move the javascript code that's using knockout outside the html file? I want to create a separate file where everything is handled (or as much as possible). Also the templating should still work. Thanks in advance!

EDIT: Changes made. I have added the require.js in my Scripts folder and made an app.js and viewmodel.js file. But this still won't work. Any help would be very much appreciated :)

EDIT2: Almost there, Rumesh Eranga gave the right answer with using require.js. I only have a little problem left with my binding. 'data-bind="text: $(item.name)"' won't show the name, only '[object Object]'.

EDIT3: SOLVED!

This is the HTML file:

<head>
<script type="text/javascript" data-main="Script/app.js" src="Scripts/require.js"></script>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="Scripts/jquery.tmpl.js"></script>
<script id="shoppingItemTemplate" type="text/html">
    <li><span data-bind="text: item.name"></span></li>
</script>

<div id="ActiveShoppingList">
<h2>Shopping items</h2>
<div id="ActiveList">
    <ul data-bind="template: {name:'shoppingItemTemplate', foreach: items, as:'item'}"></ul>
    <button data-bind="click:addItem">Add item</button>
</div>
</div>
</body>

Here is my Script/app.js:

require(['knockout-3.2.0', 'viewmodel'], function(ko, viewmodel) {
ko.applyBindings(new viewmodel);
});

And here is my Script/viewmodel.js:

define(['knockout-3.2.0'], function(ko) {
return function viewmodel (){
    this.items = ko.observableArray([new item("item1"), new item("item2")]);
    this.addItem = function()
        {
            this.items.push(new item("new item"));
        };
};

function item(name)
{
    return { name: ko.observable(name) };
}
});
1
Couldn't you load the external HTML partial via ajax, and upon loading that HTML file, just applyBindings at that time?dlane

1 Answers

2
votes

Use Asynchronous Module Definition (AMD) With RequireJs.

Good article on Require and knockout can be found here.

Quoting from the site.

HTML

<html>
    <head>
        <script type="text/javascript" data-main="scripts/init.js" src="scripts/require.js"></script>
    </head>
    <body>
        <p>First name: <input data-bind="value: firstName" /></p>
        <p>First name capitalized: <strong data-bind="text: firstNameCaps"></strong></p>
    </body>
</html>

scope/init.js

require(['knockout-x.y.z', 'appViewModel', 'domReady!'], function(ko, appViewModel) {
    ko.applyBindings(new appViewModel());
});

scripts/appViewModel.js

// Main viewmodel class
define(['knockout-x.y.z'], function(ko) {
    return function appViewModel() {
        this.firstName = ko.observable('Bert');
        this.firstNameCaps = ko.pureComputed(function() {
            return this.firstName().toUpperCase();
        }, this);
    };
});

According to the code snippet given above you can see that you can make your view model code separate from the html and even can be modularize which is much helpful.