I have a set of cascading dropdown lists which are used to select a house address. We break apart the address in this order:
- Street Name (e.g. 10th, 11th, Main)
- Street Suffix (e.g. St, Ave)
- Street Direction
- Street Number (house number)
I am using knockout to generate the values in the dropdowns which are pulled from the database via REST queries. I have this working well, except for a single edge case.
First let me tell you a bit about addresses (when they are broken apart like this). There is always a street name and there is always a street number. Suffix and direction aren't always used. So I might have a 100 Savanna South (Savanna South being the street name), or 101 Main St. I have these scenarios working assuming that the suffix and direction change.
The problem is that when I switch from say 10th to 11th. They both only have a suffix of "Street" and both have only one direction of "West". When I make the change, suffix and direction don't change which does not trigger the appropriate subscribes to pull the next set of data. So if I change from 10th to 11th, the house numbers don't update.
function AddViewModel() {
/* Address */
self.StreetName = ko.observable('');
self.StreetNames = ko.observableArray([""]);
self.StreetName.subscribe(function (val) {
if ((val !== undefined && val !== null && val !== '') && val !== viewModel.StreetType()) {
getStreetTypes(val);
}
});
self.StreetType = ko.observable('');
self.StreetTypes = ko.observableArray([]);
self.StreetType.subscribe(function (val) {
if (val !== undefined && val !== null && val !== '') {
alert("I changed to " + val);
getStreetDirections(self.StreetName, val);
}
});
self.StreetDirection = ko.observable('');
self.StreetDirections = ko.observableArray([]);
self.StreetDirection.subscribe(function (val) {
if (val !== undefined && val !== null && val !== '') {
getStreetNumbers(self.StreetName, self.StreetType, val);
}
});
self.StreetNumber = ko.observable('');
self.StreetNumbers = ko.observableArray([]);
self.StreetNumber.subscribe(function (val, e) {
if (val !== undefined && val !== null && val !== '') {
$.get('/api/gis/addressview/getaddress',
{ streetName: $('#StreetName').val(), streetType: $('#StreetType').val(), streetDirection: $('#StreetDirection').val(), streetNumber: val },
function (result) {
loadAddresses(result);
}, 'json');
}
});
}
// Get the street types
function getStreetTypes(streetName) {
$.get('/api/gis/cascadingaddress/getstreettypes', { streetName: streetName }, function (result) {
viewModel.StreetTypes(result);
// If there is only one street type, load it.
if (result.length === 1) {
if (result[0] !== "" && result[0] !== " ") {
viewModel.StreetType(result[0]);
viewModel.StreetType.notifySubscribers();
} else {
getStreetDirections(streetName, result[0]);
viewModel.StreetType.notifySubscribers();
}
}
}, 'json');
}
function getStreetDirections(streetName, streetType) {
$.get('/api/gis/cascadingaddress/getstreetdirections', { streetName: streetName, streetType: streetType }, function (result) {
viewModel.StreetDirections(result);
// If there is only one street direction, load it
if (result.length === 1) {
if (result[0] !== "" && result[0] !== " ") {
viewModel.StreetDirection(result[0]);
viewModel.StreetDirection.valueHasMutated();
} else {
getStreetNumbers(streetName, streetType, result[0]);
viewModel.StreetDirection.valueHasMutated();
}
}
}, 'json');
}
function getStreetNumbers(streetName, streetType, streetDirection) {
$.get('/api/gis/cascadingaddress/getstreetnumbers', { streetName: streetName, streetType: streetType, streetDirection: streetDirection }, function (result) {
viewModel.StreetNumbers(result);
}, 'json');
}
I have been trying several things from doing a jQuery $.trigger('change')
on the field to what you see above with adding .valueHasMutated()
. I could write elaborate code to check if the street name has changed, but the suffix and direction hasn't, then reload the street numbers, but I am trying to keep within the subscribe framework if possible.
Can anyone point me in the right direction to either trigger the .subscribe()
function or how to take another approach?
NOTE: I really can't do a JSFiddle given that the REST endpoints are in a private network and are not publicly available. Otherwise I would provide one.
.valueHasMutated()
, how about declaring the observables asko.observable('').extend({notify: 'always'});
? From here. – Fecit