Ad

Malformed JSON When Loading $scope.model.value In Custom Umbraco Data Type

- 1 answer

I'm occasionally noticing strange behaviour in the data that Umbraco initializes my data types $scope.model.value value with.

I'm working with Umbraco 7.11.1, and my custom data type is built around a complex JSON based data model.

During "Save and Publish" (from the Umbraco back-office), Umbraco seems to accept the JSON that my controller has stored in $scope.model.value - no error dialogs are displayed, console errors logged, etc.

When the back-office reloads however, Umbraco attempts to initialize my data type with a partial, malformed JSON string, rather than the expected JSON object (ie that was previously saved).

I'm following the regular pattern for implementing a custom data type, via an angularjs controller:

angular.module('umbraco')
.controller('MyDataType', ['$scope', function ($scope) {

    var loadedData = $scope.model.value;

    // Do stuff with "loadedData"

    $scope.model.value = loadedData;
}])

The issue seems to occur when I have a large amount of data in my JSON model (ie json that would serialize to ~150 characters or more)

Is there a limit to the amount of data that I can store in an Umbraco data type? Or is there something else that I am overlooking here?

Ad

Answer

The solution to this problem was to sanitize the JSON data that my controller stored in $scope.model.value.

It seems that Umbraco is sensitive to the extra metadata "stuff" that angularjs drops into scope variables ("$$hashKey", etc) and this appears to be what caused my datatype to be subsequently initialized with a malformed JSON string rather than the expected JSON object.

In the end, I opted to:

  1. clone the model value (ie $scope.myModel as shown below) that my data type was initialized with
  2. set up a $watcher to synchronize $model.scope.value with any changes made to $scope.myModel
  3. during synchronization, store a sanitized clone of $scope.myModel (ie that excludes internal angular metadata like "$$hashKey") in $model.scope.value

Example pseudo code demonstrating solution:

angular.module('umbraco')
.controller('MyDataType', ['$scope', function ($scope) {

    $scope.myModel = cloneValue($scope.model.value)

    var endWatcher = $scope.$watch('myModel', function() { 

        $scope.model.value = cloneAndSanitizeMyModel($scope.myModel)
    });

    $scope.$on('$destroy', function() {
        endWatcher();
    });
}])
Ad
source: stackoverflow.com
Ad