This is a migrated thread and some comments may be shown as answers.

asKendoDataSource not working on iPhone

5 Answers 69 Views
AppBuilder Windows client
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Richard
Top achievements
Rank 1
Richard asked on 24 Jul 2013, 08:15 PM
I'm using sqlite + jaydata + kendo in Icenium. I also uses Required.js. I know jaydata 1.3.1 doesn't work well with required.js. But after commenting out the first two lines of code, everything seems working great. Then I found this issue: asKendoDataSource doesn't work on iPhone. The code is simple, it looks like this:
[code]       dataSource = scmsDb.WorkOffers.asKendoDataSource();
        $("#listview").kendoMobileListView({
                    dataSource: dataSource,
                    template: $("#listviewHeadersTemplate").text()
               });
           });[/code]
It works well in Icenium Graphite simulator and Android devices. 
It's hard for me to provide more details because I don't get any error message. It's just that the listview not binding. I'm hoping someone experience the same problem and know the answer. I'll also try on jaydata forum.

Thanks in advance.

Richard

5 Answers, 1 is accepted

Sort by
0
Blake
Top achievements
Rank 1
answered on 27 Jul 2013, 05:33 PM
Have you made any discoveries?  I'm running into the same issue.
0
Richard
Top achievements
Rank 1
answered on 27 Jul 2013, 09:07 PM
No luck.
0
Blake
Top achievements
Rank 1
answered on 28 Jul 2013, 05:39 AM
Just solved this with a simple fix.  Apparently ios doesn't like "console.dir" so I commented them all out in the kendo.js file for the jaydatamodule.  Here's my file that works.

// JayData 1.2.7
// Dual licensed under MIT and GPL v2
// Copyright JayStack Technologies (http://jaydata.org/licensing)
//
// JayData is a standards-based, cross-platform Javascript library and a set of
// practices to access and manipulate data from various online and offline sources.
//
// Credits:
//     Hajnalka Battancs, Dániel József, János Roden, László Horváth, Péter Nochta
//     Péter Zentai, Róbert Bónay, Szabolcs Czinege, Viktor Borza, Viktor Lázár,
//     Zoltán Gyebrovszki, Gábor Dolla
//
// More info: http://jaydata.org
(function ($data) {
 
    var oldProcessor = $data.Entity.inheritedTypeProcessor;
 
    $data.kendo = {};
    $data.kendo.BaseModelType = kendo.data.Model.define({
        init: function (data) {
            kendo.data.Model.fn.init.call(this, data);
        }
    });
 
 
    var kendoTypeMap = {
        "$data.Blob": "string",
        "$data.String": "string",
        "$data.Boolean": "boolean",
        "$data.Integer": "number",
        "$data.Number": "number",
        "$data.Date": "date"
    }
 
    $data.Entity.inheritedTypeProcessor = function (type) {
 
        var memberDefinitions = type.memberDefinitions;
 
        function getKendoTypeName(canonicType, pd) {
            return kendoTypeMap[canonicType] || 'object';
        };
 
 
 
        function createKendoModel(options) {
            ///<param name="options">Contains options.owningContextType if initialized in a scope of a context</param>
            var memberDefinitions = type.memberDefinitions,
                fields = {};
            //debugger;
            function getNullable(canonicType, pd) {
                if (canonicType === "$data.Boolean") {
                    //grid validation errs on requied/nonnull bools
                    return true;
                }
                return pd.required !== true;
            };
 
            function getRequired(canonicType, pd) {
                if ("$data.Boolean" === canonicType) {
                    return false;
                }
                return pd.required || "nullable" in pd ? !(pd.nullable) : false;
            }
 
            memberDefinitions
                .getPublicMappedProperties()
                .forEach(function (pd) {
                    var canonicType = $data.Container.resolveName(pd.type);
                    //if (pd.dataType !== "Array" && !(pd.inverseProperty)) {
                    fields[pd.name] = {
                        //TODO
                        type: getKendoTypeName(canonicType, pd),
                        nullable: getNullable(canonicType, pd),
                        defaultValue: pd.defaultValue,
                        //nullable: false,
                        //nullable:  "nullable" in pd ? pd.nullable : true,
                        editable: !pd.computed,
                        //defaultValue: true,
                        //defaultValue: 'abc',
                        //defaultValue: pd.type === "Edm.Boolean" ? false : undefined,
                        validation: {
                            required: getRequired(canonicType, pd)
                        }
                    }
 
                    //};
                });
 
            function setInitialValue(obj, memDef) {
                return;
                //if (!obj[memDef.name]) {
                //    function getDefault() {
                //        switch ($data.Container.resolveType(memDef.type)) {
                //            case $data.Number: return 0.0;
                //            case $data.Integer: return 0;
                //            case $data.Date: return new Date();
                //            case $data.Boolean: return false;
                //        }
                //    }
 
                //    obj[memDef.name] = getDefault();
 
                //}
            }
 
            //console.dir(memberDefinitions.getPublicMappedMethods());
            var modelDefinition = {
                fields: fields,
                init: function (data) {
                    //console.dir(arguments);
 
                    var ctxType = options && options.owningContextType || undefined;
 
                    var contextSetTypes = [];
                    if (options && options.owningContextType) {
                        contextSetTypes = options.owningContextType
                                                     .memberDefinitions
                                                     .getPublicMappedProperties()
                                                     .filter(function (pd) { return $data.Container.resolveType(pd.type) === $data.EntitySet })
                                                     .map(function (pd) { return $data.Container.resolveType(pd.elementType) });
 
                    }
 
                    var newInstanceOptions = {
                        entityBuilder: function (instance, members) {
                            members.forEach(function (memberInfo) {
                                if (!(memberInfo.key === true) && (memberInfo.required === true || memberInfo.nullable === false)) {
                                    var memberType = $data.Container.resolveType(memberInfo.type);
                                    if (memberType.isAssignableTo && memberType.isAssignableTo($data.Entity) && contextSetTypes.indexOf(memberType) === -1) {
                                        //it's a complex property
                                        var _data;
                                        if (data) {
                                            _data = data[memberInfo.name];
                                        };
                                        instance[memberInfo.name] = new memberType(_data, newInstanceOptions);
                                    } else {
                                        setInitialValue(instance, memberInfo);
                                    }
                                }
                            });
                        }
                    }
 
                    var jayInstance = data instanceof type ? data : new type(data, newInstanceOptions);
 
                    var seed = jayInstance.initData;
 
                    var feed = {};
                    //TODO create precompiled strategy
                    for (var j in seed) {
                        var md = type.getMemberDefinition(j);
                        var seedValue = seed[j];
                        if (seedValue instanceof $data.Entity) {
                            var kendoInstance = seedValue.asKendoObservable();
                            feed[j] = kendoInstance;
                        } else if (md && md.type === "Array") {
                            var jayType = $data.Container.resolveType(md.elementType);
                            var kendoType = jayType.asKendoModel();
                            var feedValue = new kendo.data.ObservableArray(seed[j], kendoType);
                            feed[j] = feedValue;
                        } else {
                            feed[j] = seedValue;
                        }
                    }
 
                    var self = this;
                    this.innerInstance = function () { return jayInstance }
 
 
 
                    //kendo.data.Model.fn.init.call(this, feed);
                    $data.kendo.BaseModelType.fn.init.call(this, feed);
 
                    jayInstance.propertyChanged.attach(function (obj, propinfo) {
                        var jay = this;
                        var newValue = propinfo.newValue;
                        if (!jay.changeFromKendo) {
                            newValue = newValue ? (newValue.asKendoObservable ? newValue.asKendoObservable() : newValue) : newValue;
                            jayInstance.changeFromJay = true;
                            self.set(propinfo.propertyName, propinfo.newValue);
                            delete jayInstance.changeFromJay;
                        }
                    });
 
                    this.bind("set", function (e) {
                        var propName = e.field;
                        var propNameParts = propName.split(".");
                        jayInstance.changeFromKendo = true;
                        if (propNameParts.length == 1) {
                            var propValue = e.value;
                            if (!jayInstance.changeFromJay) {
                                propValue = propValue.innerInstance ? propValue.innerInstance() : propValue;
                                jayInstance[propName] = propValue;
                                if (options && options.autoSave) {
                                    jayInstance.save();
                                }
                            }
                        } else {
                            var rootProp = jayInstance[propNameParts[0]];
                            if (rootProp instanceof $data.Entity) {
                                jayInstance[propNameParts[0]] = rootProp;
                            }
                        }
                        delete jayInstance.changeFromKendo;
                    });
                    if (options && options.newInstanceCallback) {
                        options.newInstanceCallback(jayInstance);
                    }
 
                },
                save: function () {
                    //console.log("item.save", this, arguments);
                    return this.innerInstance().save();
                },
                remove: function () {
                    return this.innerInstance().remove();
                }
 
            };
 
            var keyProperties = memberDefinitions.getKeyProperties();
            switch (keyProperties.length) {
                case 0:
                    break;
                case 1:
                    modelDefinition.id = keyProperties[0].name;
                    break;
                default:
                    console.warn("entity with multiple keys not supported");
                    break;
            }
            console.log("md", modelDefinition);
 
            var returnValue = kendo.data.Model.define($data.kendo.BaseModelType, modelDefinition);
 
 
            //returnValue.readAll
 
            //TODO align with kendoui concept
            //for (var j in returnValue.prototype.defaults) {
            //    returnValue.prototype.defaults[j] = undefined;
            //}
            //console.log("default", returnValue.prototype.defaults)
            return returnValue;
        }
 
        function asKendoModel(options) {
            var cacheObject = options || type;
            return cacheObject.kendoModelType || (cacheObject.kendoModelType = createKendoModel(options));
        }
 
        function asKendoObservable(instance, options) {
 
            var kendoModel = type.asKendoModel(options);
            return new kendoModel(instance);
        }
 
        type.asKendoModel = asKendoModel;
        //type.asKendoModelType = asKendoModel;
 
        type.prototype.asKendoObservable = function (options) {
            var self = this;
 
            var kendoObservable = asKendoObservable(this, options);
 
            return kendoObservable;
        }
 
        function r(value){
            return value || '';
        }
        function registerStoreAlias(type, options) {
            if (!options.provider) return;
            var key = r(options.databaseName) + r(options.tableName) + r(options.url) + r(options.apiUrl) + r(options.oDataServiceHost);
            var storeDef = {
                provider: options.provider,
                databaseName: options.databaseName,
                tableName: options.tableName,
                dataSource: options.url,
                apiUrl: options.apiUrl,
                oDataServiceHost: options.oDataServiceHost
            };
            Object.keys(storeDef).forEach(function (k) {
                delete options[k];
            });
 
            type.setStore(key, storeDef);
            return key;
        }
 
        type.asKendoDataSource = function (options, modelOptions, storeAlias) {
            options = options || {};
            var mOptions = modelOptions || {};
            var salias = registerStoreAlias(type, options) || storeAlias;
            var token = $data.ItemStore._getStoreAlias(type, salias);
            var ctx = $data.ItemStore._getContextPromise(token, type);
            var set = ctx.getEntitySetFromElementType(type);
            return set.asKendoDataSource(options, mOptions);
        };
 
        if (oldProcessor) {
            oldProcessor(type);
        }
    }
    $data.Queryable.addMember("asKendoColumns", function (columns) {
        //console.log('col', this, arguments);
        var result = [];
        columns = columns || {};
        var showComplex = columns['$showComplexFields'] === true;
        delete columns['$showComplexFields'];
 
        this.defaultType
            .memberDefinitions
            .getPublicMappedProperties()
            .forEach(function (pd) {
                //if (pd.dataType !== "Array" && !(pd.inverseProperty)) {
                if (showComplex || kendoTypeMap[$data.Container.resolveName(pd.type)]) {
                    var col = columns[pd.name] || {};
                    var colD = { field: pd.name };
                    $.extend(colD, col)
                    result.push(colD);
                }
                //}
            });
 
        function append(field) {
            field = Array.isArray(field) ? field : [field];
            var result = this.concat(field);
            return prepareResult(result);
        }
 
        function prepend(field) {
            field = Array.isArray(field) ? field : [field];
            var result = field.concat(this);
            return prepareResult(result);
        }
 
        function setColumn(colName, def) {
            var it = this.filter(function (item) { return item.field == colName })[0];
            $.extend(it, def);
            return this;
        }
 
 
        function prepareResult(r) {
            r.prepend = prepend;
            r.append = append;
            r.setColumn = setColumn;
            return r;
        }
        return prepareResult(result);
        //return ['id', 'Year', 'Manufacturer', { command: ["edit", "create", "destroy", "update"] }];
    }),
 
    //, { command: ["edit", "create", "destroy", "update"]}
    $data.EntityContext.addProperty("EntitySetNames", function () {
        var self = this;
        //var sets = Object.keys(self._entitySetReferences);
        //return sets;
        return Object.keys(self._entitySetReferences).map(function (set) {
            return self._entitySetReferences[set].tableName;
        });
    });
 
 
    $data.Queryable.addMember("asKendoModel", function (options) {
        options.owningContextType = options.owningContextType || this.entityContext.getType();
        return this.defaultType.asKendoModel(options);
    });
 
    $data.Queryable.addMember("asKendoRemoteTransportClass", function (modelItemClass) {
        var self = this;
        var ctx = self.entityContext;
        function reset() {
            ctx.stateManager.reset();
        };
        var TransportClass = kendo.data.RemoteTransport.extend({
            init: function () {
                this.items = [];
            },
            read: function (options) {
                var query = self;
 
                query.entityContext.onReady().then(function () {
                    var _this = this;
                    var q = query;
                    var sp = query.entityContext.storageProvider;
                    var withInlineCount = query.entityContext.storageProvider.supportedSetOperations.withInlineCount;
                    var withLength = (!withInlineCount) && query.entityContext.storageProvider.supportedSetOperations.length;
 
                    if (withInlineCount) {
                        q = q.withInlineCount();
                    }
 
                    if (options.data.filter) {
                        var filter = "";
                        var thisArg = {};
                        options.data.filter.filters.forEach(function (f, index) {
                            if (index > 0) { filter += options.data.filter.logic == "or" ? " || " : " && "; }
 
                            //console.log(filter, f);
 
                            switch (f.operator) {
                                case 'eq':
                                    filter += "it." + f.field;
                                    filter += " == this." + f.field;
                                    break;
                                case 'neq':
                                    filter += "it." + f.field;
                                    filter += " != this." + f.field;
                                    break;
                                case 'startswith':
                                    filter += "it." + f.field;
                                    filter += ".startsWith(this." + f.field + ")";
                                    break;
                                case 'contains':
                                    filter += "it." + f.field;
                                    filter += ".contains(this." + f.field + ")";
                                    break;
                                case 'doesnotcontain':
                                    filter += "!";
                                    filter += "it." + f.field;
                                    filter += ".contains(this." + f.field + ")";
                                    break;
                                case 'endswith':
                                    filter += "it." + f.field;
                                    filter += ".endsWith(this." + f.field + ")";
                                    break;
                                case 'gte':
                                    filter += "it." + f.field;
                                    filter += " >= this." + f.field;
                                    break;
                                case 'gt':
                                    filter += "it." + f.field;
                                    filter += " > this." + f.field;
                                    break;
                                case 'lte':
                                    filter += "it." + f.field;
                                    filter += " <= this." + f.field;
                                    break;
                                case 'lt':
                                    filter += "it." + f.field;
                                    filter += " < this." + f.field;
                                    break;
                                default:
                                    console.log('unknown operator', f.operator);
                                    break;
                            }
                            thisArg[f.field] = f.value;
                        })
                        q = q.filter(filter, thisArg);
                    }
                    var allItemsQ = q;
 
                    if (options.data.sort) {
                        options.data.sort.forEach(function (s) {
                            q = q.order((s.dir == 'desc' ? "-" : "") + s.field);
                        })
                    }
 
                    if (options.data.skip) {
                        q = q.skip(options.data.skip);
                    }
                    if (options.data.take) {
                        q = q.take(options.data.take);
                    }
 
                    //Data.defaultHttpClient.enableJsonpCallback = true;
                    var promises = [];
 
                    promises.push(q.toArray());
                    //var ta = q.toArray();
                    if (withLength) {
                        promises.push(allItemsQ.length());
                    } else if (!withInlineCount) {
                        promises.push(allItemsQ.toArray());
                    }
 
                    console.log(promises);
                    jQuery.when.apply(this, promises).then(function (items, total) {
                        //console.dir(arguments);
                        //var result = items.map(function (item) { return item instanceof $data.Entity ? new model(item.initData) : item; });
                        var result = items.map(function (item) {
                            var d = (item instanceof $data.Entity) ? item.initData : item;
                            var kendoItem = item.asKendoObservable();
                            return kendoItem;
                        });
                        var r = {
                            data: result,
                            total: withInlineCount ? items.totalCount : (withLength ? total : total.length)
                        }
                        console.log(r);
                        options.success(r);
                    }).fail(function() {
                        console.log("error in create");
            options.error({}, arguments);
            });
                });
            },
            create: function (options, model) {
                var query = self;
                query.entityContext.onReady().then(function () {
                    if (model.length > 1) {
                        var modelItems = [];
                        model.forEach(function (modelItem) {
                            modelItems.push(modelItem.innerInstance());
                        });
                        ctx.addMany(modelItems);
                        ctx.saveChanges().then(function () {
                            var data = [];
                            modelItems.forEach(function (modelItem) {
                                data.push(modelItem.initData);
                            });
                            options.success({ data: data });
                        }).fail(function () {
                            console.log("error in create");
                            options.error({}, arguments);
                            ctx.stateManager.reset();
                        });
                    } else {
                        //console.log("save single");
                        //console.dir(ctx.storeToken);
                        model[0]
                            .innerInstance()
                            .save(ctx.storeToken)
                            .then(function () {
                                options.success({ data: model[0].innerInstance().initData });
                            })
                .fail(function() {
                                console.log("error in create");
                options.error({}, arguments);
                });
                    }
                });
            },
            update: function (options, model) {
                //console.log("update");
                //console.dir(arguments);
                var query = self;
                query.entityContext.onReady().then(function () {
                    if (model.length > 1) {
                        var items = model.map(function (item) { return item.innerInstance() });
                        items.forEach(function (item) {
                            ctx.attach(item, true);
                        });
                        ctx.saveChanges().then(function () {
                            options.success();
                        }).fail(function () {
                            ctx.stateManager.reset();
                            //alert("error in batch update");
                            options.error({}, arguments);
                        });
                    } else {
                        model[0].innerInstance().save().then(function (item) {
                            options.success();
                        }).fail(function () {
                 //alert("error in update")
                            options.error({}, arguments);
            });
                    }
                });
            },
 
            destroy: function (options, model) {
                var query = self;
                query.entityContext.onReady().then(function () {
                    if (model.length > 1) {
                        model.forEach(function (item) {
                            ctx.remove(item.innerInstance());
                        });
                        ctx.saveChanges().then(function () {
                            options.success({ data: options.data });
                        }).fail(function () {
                            ctx.stateManager.reset();
                            //alert("error in save:" + arguments[0]);
                            options.error({}, "error", options.data);
                        });
                    } else {
                        model[0].innerInstance().remove().then(function () {
                            options.success({ data: options.data });
                        }).fail(function () {
                            ctx.stateManager.reset();
                            //alert("error in save:" + arguments[0]);
                            options.error({}, "error", options.data);
                        });
                    }
                });
            },
            setup: function () {
                console.log("setup");
                //console.dir(arguments);
            }
        });
        return TransportClass;
    });
 
    var jayDataSource = kendo.data.DataSource.extend({
        init: function () {
            kendo.data.DataSource.fn.init.apply(this, arguments);
        },
        createItem: function (initData) {
            var type = this.options.schema.model;
            return new type(initData);
        },
        _promise: function (data, models, type) {
            var that = this,
                extend = $.extend,
                transport = that.transport;
 
            return $.Deferred(function (deferred) {
                transport[type].call(transport, extend({
                    success: function (response) {
                        deferred.resolve({
                            response: response,
                            models: models,
                            type: type
                        });
                    },
                    error: function (response, status, error) {
                        deferred.reject(response);
                        that.error(response, status, error);
                    }
                }, data), models
                );
            }).promise();
        }
    });
 
    $data.kendo = $data.kendo || {};
 
    $data.kendo.defaultPageSize = 25;
 
    $data.Queryable.addMember("asKendoDataSource", function (ds, modelOptions) {
        var self = this;
 
        modelOptions = modelOptions || {};
        var model = self.asKendoModel(modelOptions);
 
        ds = ds || {};
        //unless user explicitly opts out server side logic
        //we just force it.
        ds.serverPaging = ds.serverPaging || true;
        ds.serverFiltering = ds.serverFiltering || true;
        ds.serverSorting = ds.serverSorting || true;
        ds.pageSize = ds.pageSize === undefined ? $data.kendo.defaultPageSize : ds.pageSize;
 
        var TransportClass = self.asKendoRemoteTransportClass(model);
        ds.transport = new TransportClass();
 
        ds.schema = {
            model: model,
            data: "data",
            total: "total"
        };
        return new jayDataSource(ds);
    });
 
    kendo.data.binders.submit = kendo.data.Binder.extend({
        init: function (element, bindings, options) {
            kendo.data.Binder.fn.init.call(this, element, bindings, options);
            $(element).bind("submit", function () {
                var obj = bindings.submit.source;
                var fn = obj[bindings.submit.path];
                if (typeof fn === 'function') {
                    fn.apply(obj, arguments);
                    return false;
                }
 
            });
        },
        refresh: function () {
        }
    });
 
})($data);
0
Richard
Top achievements
Rank 1
answered on 28 Jul 2013, 03:42 PM
Wonderful! I removed all "console.dir" statements from Kendo.min.js file and it worked on my iPhone. Thanks for your help. I have customized Jaydata.min.js to make it work with required.js. Now more customized code in Kendo.min.js. Getting messy!
0
Richard
Top achievements
Rank 1
answered on 28 Jul 2013, 03:43 PM
By the way, I'll also post the answer on JayData forum so that they can fix it in the next version.
Tags
AppBuilder Windows client
Asked by
Richard
Top achievements
Rank 1
Answers by
Blake
Top achievements
Rank 1
Richard
Top achievements
Rank 1
Share this question
or