Reputation: 962
I have spent some time trying to unscramble this issue. I have a page that I would like to be used by a beauty salon owner to manage two things:
To select a 'view' I am using a toggle that is based on Knockout's visible binding:
So when a radio button is clicked a div is being rendered and another hidden:
<div id="selectingScopes" class="col-xs-6 col-md-4">
<fieldset>
<legend>View:</legend>
<div id="radioControls" class="switch-toggle well">
<input jsf:id="appointmentsRadio" name="appointmentsRadio" type="radio"
data-bind="checked: selectedScope" value="#{bigcopy.appointmentsLabel}"/>
<label for="appointmentsRadio" onclick="">#{bigcopy.appointmentsLabel}</label>
<input jsf:id="specialdaysRadio" name="specialdaysRadio" type="radio"
data-bind="checked: selectedScope" value="#{bigcopy.specialDaysLabel}"/>
<label for="specialdaysRadio" onclick="">#{bigcopy.specialDaysLabel}</label>
<a class="btn btn-primary"></a>
</div>
</fieldset>
</div>
<div id="appointmentsModel" class="row" data-bind="fadeVisible: selectedScope()==='#{bigcopy.appointmentsLabel}'">
<ui:include src="includes/appointmentsManagement.xhtml"/>
</div>
<div class="row" data-bind="fadeVisible: selectedScope()==='#{bigcopy.specialDaysLabel}'">
<ui:include src="includes/specdaysManagement.html"/>
</div>
In the same time I want to bind the "appointmentsModel" div above to a different view model that will be responsible only for managing the table of appointments that have to be uploaded from the server. This is the js file sifted of irrelevant clutter:
var restServiceRoot = "localhost:8080/RimmaNew/rest";
var scopeSelector = {
selectedScope: ko.observable()
};
ko.applyBindings(scopeSelector);
//appointments part
//Initial load
function appointmentsModel() {
var self = this;
self.serviceURL = restServiceRoot + "/appointments";
self.Appointments = ko.observableArray([]);
$.ajax({
url: self.serviceURL,
type: 'get',
data: null,
dataType: 'json',
success: function (appointments) {
var parsed = JSON.parse(appointments);
var appointmentsArray = parsed.current;
var mappedAppointments = $.map(appointmentsArray, function(item){
return new Appointment(item);
});
self.Appointments(mappedAppointments);
},
error: function (xhr, ajaxOptions, thrownError) {
var err = xhr.responseText;
alert(err);
}
});
}
var appointmentsModelImpl = new appointmentsModel();
ko.applyBindings(appointmentsModelImpl, document.getElementById('appointmentsModel'));
My code is inspired of two books: Knockout.js (O'Reilly - Jamie Munro) and Java EE and HTML 5 Enterprise Application Development (Oracle Press) that barely touch upon the topic of having cross-bindings in KO. I equally didn't find official KO documentation to be helpful in this endeavor.
There is a stackoverflow ticket that dealt with a similar issue, but in one it was the author who answered himself - his explanation made perfect sense to himself, but the mentions of 'stopBinding' and 'controlsDescendantBindings' seemed taken out of context to the two bindings that he uses below...I can't see how to apply this to my problem...
So you would make me a huuge favor if you could either
Doing both would be fantastic.
1 The full code for the original page (xhtml) is here
4The enclosed page with the 'appointments' table
Upvotes: 0
Views: 303
Reputation: 392
Your best bet will probably be to think of your models a little bit differently. Instead of doing a separate model binding, it may make more sense to do a default appointmentsModel, then update the observables inside that.
What I would do is have a single parent binding to the body, or a containing div in the body, then submodels for the various children.
Sample JS:
var MyParentModel = function(){
var self = this;
self.selectingScopes = {
scope: ko.observable("");
};
self.appointmentModel = {
param1: ko.observable(),
param2: ko.observable()
}
};
ko.applyBindings(new MyParentModel());
Sample HTML:
<div id="appointmentsModel" data-bind="with: appointmentModel"></div>
Upvotes: 2