From 3fc706972f871695560acbee9690229943bcbd6e Mon Sep 17 00:00:00 2001 From: Nedyalko Nikolov Date: Fri, 12 Aug 2016 15:05:42 +0300 Subject: [PATCH] Fixed creating Observable object from nested JSON object. --- tests/app/data/observable-tests.ts | 10 +++++ tests/app/ui/bindable-tests.ts | 4 +- .../data/observable/observable.d.ts | 11 ++++++ .../data/observable/observable.ts | 39 ++++++++++++++----- 4 files changed, 52 insertions(+), 12 deletions(-) diff --git a/tests/app/data/observable-tests.ts b/tests/app/data/observable-tests.ts index 8ab4b08a1..8c74af4e4 100644 --- a/tests/app/data/observable-tests.ts +++ b/tests/app/data/observable-tests.ts @@ -6,6 +6,7 @@ import dependencyObservable = require("ui/core/dependency-observable"); import TKUnit = require("../TKUnit"); import types = require("utils/types"); import proxy = require("ui/core/proxy"); +import {ObservableArray} from "data/observable-array"; var TESTED_NAME = "tested"; class TestObservable extends observable.Observable { @@ -525,3 +526,12 @@ export function test_CorrectPropertyValueAfterUsingWrappedValue() { TKUnit.assertEqual(testObservable.get("property1"), testArray, "WrappedValue is used only to execute property change logic and unwrapped value should be used as proeprty value."); } + +export function test_NestedObservablesWithObservableArrayShouldNotCrash() { + let someObservableArray = new ObservableArray(); + let testObservable = observable.Observable.fromJSONRecursive({ + firstProp: "test string", + secondProp: someObservableArray + }); + TKUnit.assert(testObservable !== undefined); +} \ No newline at end of file diff --git a/tests/app/ui/bindable-tests.ts b/tests/app/ui/bindable-tests.ts index 841c9b4c2..a00081a9e 100644 --- a/tests/app/ui/bindable-tests.ts +++ b/tests/app/ui/bindable-tests.ts @@ -1265,7 +1265,7 @@ export function test_only_Bindable_BindingContext_Null_DoesNotThrow() { export function test_Observable_from_nested_json_binds_correctly() { let expectedValue = "Test"; - var model = new observable.Observable({ + let model = observable.Observable.fromJSONRecursive({ "firstObject": { "secondObject": { "dummyProperty": "text" @@ -1286,7 +1286,7 @@ export function test_Observable_from_nested_json_binds_correctly() { export function test_Observable_from_nested_json_binds_correctly_when_upper_object_is_changed() { let expectedValue = "Test"; - var model = new observable.Observable({ + let model = observable.Observable.fromJSONRecursive({ "firstObject": { "secondObject": { "dummyProperty": "text" diff --git a/tns-core-modules/data/observable/observable.d.ts b/tns-core-modules/data/observable/observable.d.ts index 142ab7e2c..2b010ec37 100644 --- a/tns-core-modules/data/observable/observable.d.ts +++ b/tns-core-modules/data/observable/observable.d.ts @@ -70,8 +70,19 @@ declare module "data/observable" { */ public static propertyChangeEvent: string; + /** + * Creates an Observable instance and sets its properties according to the supplied JSON object. + */ + public static fromJSON(json: any): Observable; + /** * Creates an Observable instance and sets its properties according to the supplied JSON object. + * This function will create new Observable for each nested object (expect arrays and functions) from supplied JSON. + */ + public static fromJSONRecursive(json: any): Observable; + + /** + * [Deprecated please use static functions fromJSON or fromJSONRecursive instead] Creates an Observable instance and sets its properties according to the supplied JSON object. */ constructor(json?: any); diff --git a/tns-core-modules/data/observable/observable.ts b/tns-core-modules/data/observable/observable.ts index 1ad93a2f2..b1917128e 100644 --- a/tns-core-modules/data/observable/observable.ts +++ b/tns-core-modules/data/observable/observable.ts @@ -51,18 +51,37 @@ export class Observable implements definition.Observable { private _observers = {}; + public static fromJSON(json: any): Observable { + let observable = new Observable(); + observable.addPropertiesFromJSON(observable, json, false); + return observable; + } + + public static fromJSONRecursive(json: any): Observable { + let observable = new Observable(); + observable.addPropertiesFromJSON(observable, json, true); + return observable; + } + + private addPropertiesFromJSON(observable: Observable, json: any, recursive?: boolean) { + let isRecursive = recursive || false; + observable._map = new Map(); + for (var prop in json) { + if (json.hasOwnProperty(prop)) { + if (isRecursive) { + if (!Array.isArray(json[prop]) && typeof json[prop] === 'object' && types.getClass(json[prop]) !== 'ObservableArray') { + json[prop] = Observable.fromJSONRecursive(json[prop]); + } + } + observable._defineNewProperty(prop); + observable.set(prop, json[prop]); + } + } + } + constructor(json?: any) { if (json) { - this._map = new Map(); - for (var prop in json) { - if (json.hasOwnProperty(prop)) { - if (!Array.isArray(json[prop]) && typeof json[prop] === 'object') { - json[prop] = new Observable(json[prop]); - } - this._defineNewProperty(prop); - this.set(prop, json[prop]); - } - } + this.addPropertiesFromJSON(this, json); } }