Offline Support between App restarts - Mobile Cordova App

5 posts, 2 answers
  1. Tobias
    Tobias avatar
    18 posts
    Member since:
    Jul 2008

    Posted 03 Apr Link to this post

    Hi,

    I´d like to develop a mobile app with telerik platform / appbuilder in cordova by using visual Studio 2015.
    The app connects to a web api over json and uses the Kendo datasource object with offlineStorage.
    So far everything is okay switching beetween online and offline connection in the simulator or in the companoin app on my iPhone.
    The problem is that I can't succed in using the offline datasource when opening the app after completely closing it before.
    (offline Storage was already writen - not the very first start of the app)

    I followed this article http://developer.telerik.com/featured/adding-offline-support-kendo-ui-mobile-app
    and also this forum post http://www.telerik.com/forums/offline-storage-sync

     

    I've got this code in my view.html:

    <ul id="list" data-click="selectItem" data-auto-bind="false" data-source="dataSource" data-role="listview" data-template="contactsTemplate" ></ul>
     
    <script type="text/x-kendo-template" id="contactsTemplate">
        <span style="font-size:medium">#: data.such_Match #</span>   -   <span style="font-size:smaller">#: data.ort #</span>
    </script>

     

    And here is my JavaScript file:

    'use strict';
     
    app.auftraegeView = kendo.observable({
        onShow: function () {},
        afterShow: function () {}
    });
    app.localization.registerView('auftraegeView');
     
    // START_CUSTOM_CODE_homeView
    // Add custom code here. For more information about custom code, see http://docs.telerik.com/platform/screenbuilder/troubleshooting/how-to-keep-custom-code-changes
     
    var crudServiceBaseUrl = "http://komserver.mnc-tec.de:9810/api";
    var dataSource = new kendo.data.DataSource({
        offlineStorage: "Offline",
        transport: {
            read: {
                url: crudServiceBaseUrl + "/Auftraege/28/2017-03-01",
                dataType: "json"
            }
        },
        schema: {
            model: {
                id: "liTourIx"
            }
        }
    });
     
    (function () {
        app.auftraegeView.set('title', 'Aufträge');
        app.auftraegeView.set('onShow', function () {
            dataSource.read();
            app.auftraegeView.set('dataSource', dataSource);
        })
     
        function checkConnection() {
            var networkState = navigator.connection.type;
            var states = {};
            states[Connection.UNKNOWN] = 'Unbekannte Verbindung';
            states[Connection.ETHERNET] = 'Ethernet Verbindung';
            states[Connection.WIFI] = 'WiFi Verbindung';
            states[Connection.CELL_2G] = 'Mobil 2G Verbindung';
            states[Connection.CELL_3G] = 'Mobil 3G Verbindung';
            states[Connection.CELL_4G] = 'Mobil 4G Verbindung';
            states[Connection.CELL] = 'Mobil allgemein Verbindung';
            states[Connection.NONE] = 'Keine Netzwerkverbindung';
            return ('Netzwerk: ' + states[networkState]);
        }
     
        document.addEventListener("online", function () {
            console.log(checkConnection());
            dataSource.online(true);
            dataSource.read();
        });
        document.addEventListener("offline", function () {
            console.log(checkConnection());
            dataSource.online(false);
        });
     
    })();
     
    // END_CUSTOM_CODE_homeView

     

    What am I doing wrong / don't understand?

    Thanks, Tobi

  2. Answer
    Anton Dobrev
    Admin
    Anton Dobrev avatar
    604 posts

    Posted 05 Apr Link to this post

    @Tobi,

    You have correctly set the auto-bind property of the list view to false, which allows for better toggling of the data source mode. 

    Also you need to read the data source in the offline event handler (to be able to start the app in offline mode). Also, you need to be able to determine in the schema.data the format of the response (see the example with a custom or local response below). 

    I have altered the provided snippet with a few tweaks as follows:

    'use strict';
      
    app.auftraegeView = kendo.observable({
        onShow: function () {
            console.log("onShow");
        },
        afterShow: function () {
             
        }
    });
    app.localization.registerView('auftraegeView');
      
    var crudServiceBaseUrl = "https://.....";
    var offlineDSKey = "Offline";
     
    var dataSource = new kendo.data.DataSource({
        offlineStorage: offlineDSKey,
        transport: {
            read: {
                url: crudServiceBaseUrl,
                dataType: "json"
            }
        },
        schema: {
            model: {
                id: "Id"
            },
             data: function(response) {
                return response.Result || response; // alternate between the server or local response, local response is always a DS-ready array
              }
        },
        change: function(){
            console.log("ds event change");
        }
    });
      
    (function () {
      
        function checkConnection() {
            var networkState = navigator.connection.type;
            var states = {};
            states[Connection.UNKNOWN] = 'Unbekannte Verbindung';
            states[Connection.ETHERNET] = 'Ethernet Verbindung';
            states[Connection.WIFI] = 'WiFi Verbindung';
            states[Connection.CELL_2G] = 'Mobil 2G Verbindung';
            states[Connection.CELL_3G] = 'Mobil 3G Verbindung';
            states[Connection.CELL_4G] = 'Mobil 4G Verbindung';
            states[Connection.CELL] = 'Mobil allgemein Verbindung';
            states[Connection.NONE] = 'Keine Netzwerkverbindung';
            return ('Netzwerk: ' + states[networkState]);
        }
      
        document.addEventListener("online", function () {
            console.log(checkConnection());
            dataSource.online(true);
            dataSource.read();
        });
        document.addEventListener("offline", function () {
            console.log(checkConnection());
            dataSource.online(false);
            // when starting offline read the data too
            dataSource.read();
        });
      
    })();
      
    // END_CUSTOM_CODE_homeView


    <div id="contactsView" data-role="view" data-bind="events: { show: onShow}" data-model="app.auftraegeView">
    <ul id="list" data-click="selectItem" data-auto-bind="false" data-source="dataSource" data-role="listview" data-template="contactsTemplate" data-show="onShow"></ul>
      
    <script type="text/x-kendo-template" id="contactsTemplate">
        <span style="font-size:medium">#: data.Id #</span>   -   <span style="font-size:smaller">#: data.firstName #</span>
    </script>
         
    </div>

    Let me know if this works for you. 


    Regards,
    Anton Dobrev
    Telerik by Progress
     

    Visit the Telerik Verified Plugins Marketplace and get the custom Cordova plugin you need, already tweaked to work seamlessly with AppBuilder.

     
  3. Tobias
    Tobias avatar
    18 posts
    Member since:
    Jul 2008

    Posted 05 Apr Link to this post

    Hi Anton,
    thanks for your replay.
    Have you forgotten this portion of js. code in your replay?

    app.auftraegeView.set('onShow', function () {
        dataSource.read();
        app.auftraegeView.set('dataSource', dataSource);
    })

     

    And why do you set "onShow" two times in DIVs data-bind and in the ULs data-show?

    Regards, Tobi

  4. Answer
    Anton Dobrev
    Admin
    Anton Dobrev avatar
    604 posts

    Posted 06 Apr Link to this post

    @Tobi

    Most of the things were made intentionally (though the data-show binding set to the list view is incorrect). 

    1. There is a correct binding to the onShow event, just with a different approach. 

    2. I am not reading the data in the onShow event because I preferred to illustrate the online/offline handling (especially because I tested in an app with a single view and it was more convenient to read it when the app starts and the connection events are triggered). Surely, you need to have the read handling in more convenient places. 

    3. I initialize the data source at an earlier point, so no need to set it in the onShow event 

    4. The correct binding of the onShow event belongs to the View (and not ListView), here I apologize for a copy-paste error. 

    This said, the above points appear to be solely at the discretion of the developer. 

    Did you get the chance to test the provided snippet - the issue breaks down to be able to detect first if the app is online/offline and instructing the data source in which mode to read the data. 

    I hope this helps. 

    Regards,
    Anton Dobrev
    Telerik by Progress
     

    Visit the Telerik Verified Plugins Marketplace and get the custom Cordova plugin you need, already tweaked to work seamlessly with AppBuilder.

     
  5. Tobias
    Tobias avatar
    18 posts
    Member since:
    Jul 2008

    Posted 06 Apr Link to this post

    Thanks Anton to clarify,

    you are my hero ;-) The main thing I missed was this line:

    //...
             data: function(response) {
                return response.Result || response;
                   // alternate between the server or local response,
                   // local response is always a DS-ready array
              }
    //...

    Regards, Tobi

Back to Top