4

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.

1
  • 1
    Have you referenced your script file in your main html with <script type="text/javascript" src="EXTERNAL.js"></script>? Commented Oct 24, 2013 at 20:15

1 Answer 1

3

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).

Sign up to request clarification or add additional context in comments.

5 Comments

I have tried this and it is still not working. I even created new files and used the exact code you have here with the needed corrections and it still does not work
Apologies. First, I should've mentioned to include Knockout and jQuery. Second, you had a typo in the main script bit which I copied. Third, I had an error in my JS example, I forgot to return the namespace such that it's saved again. I've fixed things in my answer, please have another look.
PS. If you say "it still does not work" it helps if you include your debugging info, the console explained would mention all the various errors.
the return statement did it. Thanks, the error in the ready function was not in my code, I typed it wrong here when messing with the formatting to get everything to fit in to the code block
Okidoki. Glad it helped!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.