meatherly
meatherly

Reputation: 1861

knockoutjs binding to single object in observable array

I'm new to Knockoutjs. I have a observable array of Users. Here is my User model:

function User(data) {
        this.NameID = ko.observable(data.NameID);
        this.UserID = ko.observable(data.UserID);
        this.InTime = ko.observable(data.InTime);
        this.OutTime = ko.observable(data.OutTime);
        this.Notes = ko.observable(data.Notes);
        this.StatusID = ko.observable(data.StatusID);
        this.Status = ko.observable(data.Status);
        this.InOut = ko.observable(data.InOut);
        this.Name = ko.observable(data.Name);
        return this;
    }

Then in my view model I make an array of Users. Doing the foreach in my view to show all the users in a table is easy, but I want to make a form so the current user can change the his varibles. I'm using session variable to set the UserID. Then I'm using the ko.utils.arrayFirst to find the current user from the array. I feel like i'm not making any sense here. Is there anyway to make a form to access a User? like below:

function UserViewModel() {
        var self = this;
        self.users = ko.observableArray([]);
        self.statuses = ko.observableArray([]);
        self.currentUser = ko.utils.arrayFirst(self.users(), function (user) {
                return user.UserID() == @HttpContext.Current.Session["UserID"];
        });
}

Then in my view make a form(I'm using twitter-bootstrap) like this:

       <form class="well form-horizontal">    
        <div class="control-group">
            <label class="control-label" for="Statuses">
                Status</label>
            <div class="controls">
                <select id="Statuses" data-bind="options: statuses, optionsValue: 'StatusID', optionsText: 'Stat', value: currentUser.StatusID">
                </select>
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="InTime">
                In:</label>
            <div class="controls">
                <input id="InTime" data-bind="value: currentUser.InTime" class="span1" />
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="OutTime">
                Out:</label>
            <div class="controls">
                <input id="OutTime" data-bind="value: currentUser.OutTime" class="span1" />
            </div>
        </div>
        <div class="control-group">
            <label class="control-label" for="Notes">
                Notes</label>
            <div class="controls">
                <textarea id="Notes" data-bind="value: currentUser.Notes" /></textarea>
                 <p><span style="text-align:center;"><a id="chg" class="btn btn-primary" >Update</a></span></p>
            </div>
        </div>   
       </form>

Please comment if i'm not making any sense or if you need more information to help solve my problem. Thanks!!

Upvotes: 1

Views: 4531

Answers (1)

Jason Goemaat
Jason Goemaat

Reputation: 29234

What kind of error are you getting? It looks to me like your currentUser property will get set in the constructor while the arrays look like they are empty still for one thing, maybe you're just not showing where the users are populated. Another is that you are just setting it once, you could create an observable for the user id and use a computed to find the matching user, then you can easily change the user by changing the ID later or after you set the users:

self.currentUserId = ko.observable(@HttpContext.Current.Session["UserID"]);
self.currentUser = ko.computed(function() {
    return ko.utils.arrayFirst(self.users(), function (user) {
            return user.UserID() == self.currentUserId();
    });
});

The currentUser should then be set correctly when you update your array or the currentUserId observable. If the user is an observable, you will need to call it as a function, or use the with binding on your form:

<input id="InTime" data-bind="value: currentUser().InTime" class="span1" />

<form data-bind="with: currentUser">
<input id="InTime" data-bind="value: InTime" class="span1" />

Upvotes: 4

Related Questions