1

Here i have my get method that gets the data that i want to return in order to bind it with the view page. I am having trouble wrapping my head to how i could bind this information to the view.

Get Method:

var getRoster = function () {
    Ajax.Get({
        Url: ....,
        DataToSubmit: {id: properties.Id },
        DataType: "json",
        OnSuccess: function (roleData, status, jqXHR) {

            console.log("roles:", roleData.length);

            Ajax.Get({
                Url: ...,
                DataToSubmit: { pageNumber: 1, id: properties.Id },
                DataType: "json",
                OnSuccess: function (userData, status, jqXHR) {

                    for (var x in roleData)
                    {
                        var role = roleData[x];
                        console.log(role);
                        for (var y in userData)
                        {
                            var user = userData[y];
                            if (user.ContentRole == role.ContentRole)
                            {
                                 rosterViewModel.PushUser(new userViewModel(user));
                                 console.log(user);
                            }
                        }
                        roleTypesViewModel.PushRole(new roleViewModel(role));
                    }
                } 
            });
        }
    });

 rosterViewModel.PushUser = function (user) {
        viewModel.RosterUsers.push(new userViewModel(user));
    };

roleTypesViewModel.PushRole = function (role) {
        viewModel.RosterRoleTypes.push(new roleViewModel(role));
    }

var userViewModel = function (data) {
        var _self = this;
        _self.ID = ko.observable(data.ID);
        _self.Name = ko.observable(data.Name);
        _self.Email = ko.observable(data.Email);
        _self.ContentRole = ko.observable(data.ContentRole);
    };

var roleViewModel = function (data) {
        var _self = this;
        _self.ContentRole = ko.observable(data.ContentRole);
        _self.RoleName = ko.observable(data.RoleName);
        _self.RoleRank = ko.observable(data.RoleRank);
        _self.UserCount = ko.observable(data.UserCount);
    };

 var viewModel = {
        RosterRoleTypes: ko.observableArray([]),
        RosterUsers: ko.observableArray([])
    };

View:

<div id="gridView" data-bind="foreach: RosterRoleTypes">
            <h3 class="roleHeader"><span data-bind="text:RoleName"></span> 
                <span class="userCount">(<span data-bind="text:UserCount"></span>)</span>
            </h3>

            <div data-bind="template: { name: 'grid', foreach: RosterUsers}">

            </div>
        </div>

How can i bind my data to display in my view?

Masriyah
  • 2,445
  • 11
  • 49
  • 91

3 Answers3

1

If you are trying to bind multiple areas of your page to different view models, that is possible by passing in an additional parameter to your ko.applyBindings() method that you call. Your problem is that you are mixing models and view models and using them improperly. If you want to have one view model adjust your code to include all of the functions of your view model and set your models as models instead of viewmodels -

function rosterViewModel() {
    var self = this;
    self.RosterRoleTypes = ko.observableArray([]),
    self.RosterUsers = ko.observableArray([])
    self.PushUser = function (user) {
        viewModel.RosterUsers.push(new userModel(user));
    };
    self.PushRole = function (role) {
        viewModel.RosterRoleTypes.push(new roleModel(role));
    };
self.getRoster = function () {
    Ajax.Get({
        Url: ....,
        DataToSubmit: {id: properties.Id },
        DataType: "json",
        OnSuccess: function (roleData, status, jqXHR) {
            Ajax.Get({
                Url: ...,
                DataToSubmit: { pageNumber: 1, id: properties.Id },
                DataType: "json",
                OnSuccess: function (userData, status, jqXHR) {

                    for (var x in roleData)
                    {
                        var role = roleData[x];
                        for (var y in userData)
                        {
                            var user = userData[y];
                            if (user.ContentRole == role.ContentRole)
                            {
                                 self.PushUser(new userModel(user));
                            }
                        }
                        self.PushRole(new roleModel(role));
                    }
                } 
            });
        }
    });
}

var userModel = function (data) {
        var _self = this;
        _self.ID = ko.observable(data.ID);
        _self.Name = ko.observable(data.Name);
        _self.Email = ko.observable(data.Email);
        _self.ContentRole = ko.observable(data.ContentRole);
    };

var roleModel = function (data) {
        var _self = this;
        _self.ContentRole = ko.observable(data.ContentRole);
        _self.RoleName = ko.observable(data.RoleName);
        _self.RoleRank = ko.observable(data.RoleRank);
        _self.UserCount = ko.observable(data.UserCount);
    };

ko.applyBindings(new rosterViewModel());

This assumes you want to use a single view model for your view. If you are combining multiple content areas that should be bound separately you can create two view models and merge them as shown in this question - KnockOutJS - Multiple ViewModels in a single View - or you could also bind them separately by passing in an additional parameter to the ko.applyBindings() method as showm here - Example of knockoutjs pattern for multi-view applications

Community
  • 1
  • 1
PW Kad
  • 14,953
  • 7
  • 49
  • 82
  • I gave this a go but i got an `Unable to parse bindings` error and another one `undefined is not a function` i am still looking into seeing is it based on what we have or for something else – Masriyah Oct 08 '13 at 14:20
  • @PW Kad Its you that mix up ViewModels and models. Role and User are also ViewModels. The minute you add Observable / View logic to a model its a ViewModel – Anders Oct 08 '13 at 14:20
  • @Anders Where is any view logic inside of the models? Just because the model makes the properties an observable instance of the property does not mean the model contains any view logic... – PW Kad Oct 08 '13 at 14:25
  • The ability to two way bind against a view is not view aware logic? Its a view model trust me. Above example is not just very good, most view models also have additional stuff like computed fields etc. But its not required to be a valid view model. Just to be clear, it does not even have to have observables to be a view model, the minute you add a model (Data from server) to the viewmodel its a viewmodel in it self – Anders Oct 08 '13 at 14:32
  • The instance of the model is created in the view model, and the observable properties live there... To access the properties, you do so in the view model, to get rid of them, everything is done in the view model... The model I have listed is a class more or less that contains properties which are created by 'newing' the model, so how is there any two-way data-binding back to the model? Are you sure you read my answer? – PW Kad Oct 08 '13 at 14:38
  • in my for loops will have to change anything to connect it with the rosterViewModel() or leave as is and add the ko applybindings? – Masriyah Oct 08 '13 at 14:52
  • You should have that be a method inside of your view model for clarity. I have updated the answer to include that method inside your view model. It is now referring to the viewmodel's observableArray's, pushing into them, and everything should be 90% correct, I haven't tested it in a browser or anything though, consider making a jsFiddle if oyu need more help. – PW Kad Oct 08 '13 at 14:55
  • There is no code shown to backup where you are calling getRoster from – PW Kad Oct 08 '13 at 15:05
  • i have an init method and in it i call getRoster(), should that be rostersViewModel().getRoster()? – Masriyah Oct 08 '13 at 15:06
  • All of your view model specific code should be inside of your view model, if you are using it outside of the viewmodel then yes you need to call the object that contains getRoster which would be rostersViewModle – PW Kad Oct 08 '13 at 15:07
  • @KW Kad, we can continue our discussion here http://chat.stackoverflow.com/rooms/38801/viewmodels-and-models – Anders Oct 08 '13 at 15:11
0

All of the data that you want to bind to UI will be properties of your viewmodel as KO observable or observable arrays. Once the view model is created and its members are assigned with data(callbacks in your case), you need to apply bindings using ko.applyBindinds so that the data is bound to UI. In your case the last AJAX success callback seems to be the appropriate place.

Also your HTML makes using of template bindings however apparently there is no template defined with name 'grid'. Check on this.

Knockout tutorial link http://learn.knockoutjs.com/#/?tutorial=intro

bp4D
  • 915
  • 12
  • 20
  • I do not have enough reputation to comments. In your JS viewModel is not a function/class. It is a singleton object/object liertal. So only you are receiving "object is not a function" error. Check out different ways to create a JS object @ http://www.phpied.com/3-ways-to-define-a-javascript-class/ – bp4D Oct 08 '13 at 13:33
  • So do i have to change the structure of my `var viewModel = {..}` so that it is a function? – Masriyah Oct 08 '13 at 13:35
  • And yet, there you go commenting... For the record, you can have multiple view models for your view. – PW Kad Oct 08 '13 at 13:35
  • @PWKad could i add another viewModel as a function and use it for the view? – Masriyah Oct 08 '13 at 13:38
  • See my answer above, it should clarify for you – PW Kad Oct 08 '13 at 13:39
  • @PWKad Thanks for pointing it out. I will check on multiple view models. – bp4D Oct 08 '13 at 13:42
-1

Add

ko.applyBindings(viewModel); 

somewhere in your application.

munissor
  • 3,755
  • 22
  • 24
  • I added it and i added `var vm = new viewModel()` and added `ko.applyBindings(vm)` but i am getting this error: `Uncaught Exception (js): Uncaught TypeError: object is not a function` for the viewModel(); – Masriyah Oct 08 '13 at 13:25
  • Because viewModel is not a constructor. You have to use ko.applyBindings(viewModel); as I suggested – munissor Oct 08 '13 at 14:03