Reputation: 18684
I am trying to create a login form and a registration form on the same page. So to do so, I need two view models. I create them as below.
On my page, I have two separate divs, named "login-form" and "register-form".
I am trying to apply each view model to the respective DIV.
Note, I am binding a few fields with the same name, because the data is sourced from an MVC model.
@Html.TextBoxFor(x => x.EmailAddress, new { @class = "form-control", @placeholder = "Your Email Address", @type = "email", data_bind = "value: EmailAddress" })
That line appears in both DIVs, but each div has a separate view model assigned (or so I believed).
<script type="text/javascript">
var loginViewModel = function () {
var self = this;
EmailAddress = ko.observable("");
Password = ko.observable("");
EnableLogin = ko.computed(function () {
if (self.EmailAddress() != "" && self.Password() != "")
return true;
return false;
})
}
var registerViewModel = function () {
var self = this;
EmailAddress = ko.observable("");
Password = ko.observable("");
PasswordRetype = ko.observable("");
TimeZoneID = ko.observable(0);
EnableRegister = ko.computed(function () {
if (
self.EmailAddress() != ""
&& self.Password() != ""
&& self.PasswordRetype() != ""
&& self.Password() == self.PasswordRetype()
&& self.TimeZoneID() > 0
)
return true;
return false;
})
}
ko.applyBindings(loginViewModel, $("#login-form"));
ko.applyBindings(registerViewModel, $("#register-form"));
</script>
However, when I update the email address in the login-form's email textbox, the value gets assigned to the login-forms text box as well. So the two controls are bound somehow.
When I edit the email address in the register-form, though, it does not update in the login-form. So it seems to be one-way bound.
Is what I am doing possible? How can I bind the two separate divs to their correct view models?
Upvotes: 1
Views: 345
Reputation: 1587
You can use the second parameter of ko.applyBindings
. the second parameter tells knockout where to bind your viewModel. Check it here for more info.
The first parameter says what view model object you want to use with the declarative bindings it activates
Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.
So in this case you will have 2 applyBindings call.
Another way is to contain both of the viewModels to a higher viewModel. Like:
var mainViewModel = function(){
this.loginModel = new loginViewModel();
this.registerModel = new registerViewModel();
}
And then you can just use the with
binding for each particular divs
to access loginModel
and registerModel
.
Upvotes: 0
Reputation: 9561
The second parameter in ko.applyBindings
has to be the actual DOM node you are binding to. Currently you are trying to bind to a jQuery selector which won't work.
From the documentation:
Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.
To get this to work, either change your selector to a vanilla JS one, or use the actual DOM element from the jQuery selector:
ko.applyBindings(loginViewModel, document.getElementById('login-form'));
ko.applyBindings(registerViewModel, $("#register-form")[0]);
Upvotes: 1