Reputation: 13
Hi there I'm having problems using either ko.toJSON and ko.mapping.toJSON returning an invalid state error after I've applied the google maps binding. I'm supposed to be posting the viewmodel back to an mvc controller. I've managed to reproduce the issue in a simple viewmodel. Is there a way to strip the googlemap and marker off or is there an alternative method? What am I doing wrong?
<script src="/Scripts/knockout-2.3.0.debug.js"></script>
<script src="/Scripts/knockout.mapping-latest.debug.js"></script>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
function MyViewModel() {
var self = this;
self.test = ko.observable('Hello');
self.mapOne = ko.observable({
lat: ko.observable(12.24),
lng: ko.observable(24.54)
});
self.mapTwo = ko.observable({
lat: ko.observable(40.76),
lng: ko.observable(-73.98)
});
self.save = function () {
//Invalid state error occurs here!
var jsonData = ko.toJSON(self);
};
}
ko.bindingHandlers.map = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var mapObj = ko.utils.unwrapObservable(valueAccessor());
var latLng = new google.maps.LatLng(
ko.utils.unwrapObservable(mapObj.lat),
ko.utils.unwrapObservable(mapObj.lng));
var mapOptions = {
center: latLng,
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
mapObj.googleMap = new google.maps.Map(element, mapOptions);
mapObj.marker = new google.maps.Marker({
map: mapObj.googleMap,
position: latLng,
title: "You Are Here",
draggable: true
});
mapObj.onChangedCoord = function (newValue) {
var latLng = new google.maps.LatLng(
ko.utils.unwrapObservable(mapObj.lat),
ko.utils.unwrapObservable(mapObj.lng));
mapObj.googleMap.setCenter(latLng);
};
mapObj.onMarkerMoved = function (dragEnd) {
var latLng = mapObj.marker.getPosition();
mapObj.lat(latLng.lat());
mapObj.lng(latLng.lng());
};
mapObj.lat.subscribe(mapObj.onChangedCoord);
mapObj.lng.subscribe(mapObj.onChangedCoord);
google.maps.event.addListener(mapObj.marker, 'dragend', mapObj.onMarkerMoved);
$("#" + element.getAttribute("id")).data("mapObj", mapObj);
}
};
var viewModel = new MyViewModel();
$(document).ready(function () {
ko.applyBindings(viewModel);
});
</script>
<div id="map1Div" data-bind="style: { width: '300px', height: '300px' }, map: mapOne"></div>
<input data-bind="value: mapOne().lat" />
<input data-bind="value: mapOne().lng" />
<button class="btn btn-primary" type="submit" data-bind="click: save">Save</button>
Any help would be appreciated
Upvotes: 1
Views: 925
Reputation: 4735
The problem is caused by adding the extra google maps properties to your original viewModel. When mapping encounters them, it doesn't know what to do. If they are placed in a separate object, it seems to work. mapObjVM
is the original viewModel, mapObj
is the google maps props container:
ko.bindingHandlers.map = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
var mapObjVM = ko.utils.unwrapObservable(valueAccessor());
var mapObj = {};
var latLng = new google.maps.LatLng(
ko.utils.unwrapObservable(mapObjVM.lat),
ko.utils.unwrapObservable(mapObjVM.lng));
var mapOptions = {
center: latLng,
zoom: 6,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
mapObj.googleMap = new google.maps.Map(element, mapOptions);
mapObj.marker = new google.maps.Marker({
map: mapObj.googleMap,
position: latLng,
title: "You Are Here",
draggable: true
});
mapObj.onChangedCoord = function (newValue) {
var latLng = new google.maps.LatLng(
ko.utils.unwrapObservable(mapObjVM.lat()),
ko.utils.unwrapObservable(mapObjVM.lng()));
mapObj.googleMap.setCenter(latLng);
};
mapObj.onMarkerMoved = function (dragEnd) {
var latLng = mapObj.marker.getPosition();
mapObjVM.lat(latLng.lat());
mapObjVM.lng(latLng.lng());
};
mapObjVM.lat.subscribe(mapObj.onChangedCoord);
mapObjVM.lng.subscribe(mapObj.onChangedCoord);
google.maps.event.addListener(mapObj.marker, 'dragend', mapObj.onMarkerMoved);
$("#" + element.getAttribute("id")).data("mapObj", mapObj);
}
};
Upvotes: 2