user1060248
user1060248

Reputation:

Use KnockoutJS ViewModel in External JavaScript File

How do you create a KO.JS ViewModel in an external JS file then use it in an html file? This seems like such a simple thing but I cannot get it to work and cannot find any clear information on how to do this. If I have overlooked I apologize and will remove this if someone can point me to the answer.

EXTERNAL vm:

var myApp = (function (myApp) {
myApp.ReportViewModel = function() {
    var self = this;
    self.test = ko.observable();
  }
}(myApp || {}));

Seperate HTML File:

<!DOCTYPE html>
<html>
<head><title>My Page</title></head>
<body>
<table>
    <tr>
        <td>First Name</td>
        <td><input type="text" data-bind='value: test'/></td>
    </tr>
</table>
<h2>Hello, <span data-bind="text: test"> </span>!</h2>

<!-- reference this *before* initializing -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">       </script>
<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
<script src="myApp.js"></script>

<!-- fire off your app -->
<script>
    ($function(){
       var reportVM = new myApp.ReportViewModel();
       ko.applyBindings(reportVM);
    });
</script>

EDIT I have made the suggested changes. This is what my project now looks like but it is still not working. Also the knockout.js code is not running at all.

Upvotes: 4

Views: 7303

Answers (1)

Jeroen
Jeroen

Reputation: 63739

You're on the right path. As @nemesv comments you may need to reference the external JS before you can use it. In addition, I'd recommend creating a namespace object for your app. All this together would look like this:

<html>
<head><title>My Page</title></head>
<body>
    <table>
        <tr>
            <td>First Name</td>
            <td><input type="text" data-bind='value: test'/></td>
        </tr>
    </table>
    <h2>Hello, <span data-bind="text: test"> </span>!</h2>

    <!-- reference this first -->
    <script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

    <!-- reference this *before* initializing -->
    <script src="myApp.js"></script>

    <!-- fire off your app -->
    <script>
        $(function(){
           var reportVM = new myApp.ReportViewModel();
           ko.applyBindings(reportVM);
        });
    </script>
</body>
</html>

PS. Note that I changed new reportVM to just reportVM in the second line. It's just a var at that point, no need to "new" it. In addition, I've fixed the parentheses placement on that bit of script.

And in myApp.js have this:

var myApp = (function (myApp) {
    myApp.ReportViewModel = function() {
        var self = this;
        self.test = ko.observable("Testing 123");
    }

    return myApp;
}(myApp || {}));

This way things like ReportViewModel and other constructor functions for your app won't linger in the global namespace, but will be part of the myApp object ("namespace", if you will).

Upvotes: 3

Related Questions