Skip to content

Commit

Permalink
VisitModel callback sends correct parent names (regression from 2.1.1)
Browse files Browse the repository at this point in the history
  • Loading branch information
sagacity committed Apr 12, 2012
1 parent 04258a1 commit 043723f
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
21 changes: 13 additions & 8 deletions knockout.mapping.js
Expand Up @@ -599,7 +599,9 @@
return propertyName;
}

function visitModel(rootObject, callback, options, parentName) {
function visitModel(rootObject, callback, options, parentName, fullParentName) {
console.log("VISITING", fullParentName);

// If nested object was already mapped previously, take the options from it
if (parentName !== undefined && exports.isMapped(rootObject)) {
options = ko.utils.unwrapObservable(rootObject)[mappingProperty];
Expand All @@ -615,21 +617,22 @@
var mappedRootObject;
var unwrappedRootObject = ko.utils.unwrapObservable(rootObject);
if (!canHaveProperties(unwrappedRootObject)) {
return callback(rootObject, parentName);
return callback(rootObject, fullParentName);
} else {
// Only do a callback, but ignore the results
callback(rootObject, parentName);
callback(rootObject, fullParentName);
mappedRootObject = unwrappedRootObject instanceof Array ? [] : {};
}

visitedObjects.save(rootObject, mappedRootObject);

var origFullParentName = fullParentName;
visitPropertiesOrArrayEntries(unwrappedRootObject, function (indexer) {
if (options.ignore && ko.utils.arrayIndexOf(options.ignore, indexer) != -1) return;

var propertyValue = unwrappedRootObject[indexer];
var fullPropertyName = getPropertyName(parentName, unwrappedRootObject, indexer);

// If we don't want to explicitly copy the unmapped property...
if (ko.utils.arrayIndexOf(options.copy, indexer) === -1) {
// ...find out if it's a property we want to explicitly include
Expand All @@ -642,16 +645,18 @@
}
}

var outputProperty;
switch (exports.getType(ko.utils.unwrapObservable(propertyValue))) {
fullParentName = getPropertyName(origFullParentName, unwrappedRootObject, indexer);

var propertyType = exports.getType(ko.utils.unwrapObservable(propertyValue));
switch (propertyType) {
case "object":
case "array":
case "undefined":
var previouslyMappedValue = visitedObjects.get(propertyValue);
mappedRootObject[indexer] = (exports.getType(previouslyMappedValue) !== "undefined") ? previouslyMappedValue : visitModel(propertyValue, callback, options, fullPropertyName);
mappedRootObject[indexer] = (exports.getType(previouslyMappedValue) !== "undefined") ? previouslyMappedValue : visitModel(propertyValue, callback, options, fullPropertyName, fullParentName);
break;
default:
mappedRootObject[indexer] = callback(propertyValue, parentName);
mappedRootObject[indexer] = callback(propertyValue, fullParentName);
}
});

Expand Down
37 changes: 37 additions & 0 deletions spec/mappingBehaviors.js
Expand Up @@ -1561,3 +1561,40 @@ test('ko.mapping.visitModel on a regular object', function() {
value: 0
});
});

test('ko.mapping.visitModel on a nested mapped object', function() {
var obj = {
parts: [
{ segments: [{ a: 1 }] },
{ segments: [{ a: 2 }] }
]
};

var mapped = ko.mapping.fromJS(obj, {
parts: {
create: function(options) {
return ko.mapping.fromJS(options.data, {
segments: {
create: function(options) {
return ko.mapping.fromJS(options.data);
}
}
});
}
}
});

var expectedParents = [undefined, "parts", "parts[0]", "parts[0].segments", "parts[0].segments[0]", "parts[0].segments[0].a", "parts[1]", "parts[1].segments", "parts[1].segments[0]", "parts[1].segments[0].a"];
var expectedParentIndex = 0;

deepEqual(ko.mapping.visitModel(mapped, function (x, parentName) {
console.log(parentName, "versus", expectedParents[expectedParentIndex], ko.utils.unwrapObservable(x));
equal(parentName, expectedParents[expectedParentIndex++]);
return ko.utils.unwrapObservable(x);
}), {
parts: [
{ segments: [{ a: 1 }] },
{ segments: [{ a: 2 }] }
]
});
});

0 comments on commit 043723f

Please sign in to comment.