How to Upgrade a Sencha Touch App to Ext JS 6 Modern Toolkit – Part 3

Posted on in Ext JS 6 Sencha Touch

Advanced Universal Upgrade

This upgrade will take the most time, but your opportunities are endless. You will have the latest framework with all the new features and classes, and you can improve your application performance and code base with the new MVVM architecture. Plus, you can create universal cross-platform apps (or plan to do that in the future). Not only can you build applications for mobile phones or tablets, you can also support desktop or hybrid computers, with a component set specifically made for desktop usage.

To take this approach, my advice is to regenerate a folder structure with Sencha Cmd, with the same namespace, but this time as a universal app.

  1. Navigate to the ext framework folder and generate a project with:
    sencha generate app
    For example:
    ext> sencha generate app Dinmu ../dinmu3

    This will create a folder structure with the shared app folder, the classic folder for the classic toolkit, and a modern folder for the modern toolkit.

  2. Files

  3. Once you have this folder structure, you will need to think about which code you want to share, and which code you want to be unique for each experience.

Obviously, this means that you need to create new views, specific for desktop. (In the case of the weather application, I can assume that you already have an existing touch application, with modern toolkit views, so you will make new desktop views). Desktop components might require unique event listeners, so you probably will end up with additional view controllers. You can share view controllers from the app folder, by extending it, for example.

However, you could also choose to create unique data / models for desktop views. The screens are bigger, so you have more space to display additional data. Or maybe a mobile phone has different features (camera, geolocation, etc.) than a desktop application, so you might want to create different behaviour for certain devices. The good thing is that this is all possible. The trick here is that you move classes over from the app folder to either the classic or modern folders. You can learn more about creating universal apps in my previous blog post series.

What About File Sizes?

Are you interested in the file size of the build app.js and app.css of the Weather app? Have a look:

Sencha Touch
Ext JS 6 Modern – Basic
Ext JS 6 Modern – MVVM
app.js – minified
558kb
836kb
887kb
app.css – compiled
241kb
91kb
91kb

Ext JS 6 requires more advanced classes, so that’s why the total build will be a bit bigger. You can make your own code base smaller by switching to View Controllers, using data binding, and cleaning your model fields, which might get you an even smaller final build.

Also note, because of the new microloader, we can cache your applications way smarter, and applications can be made for offline use.

Triton Theme
Triton Theme
Triton Theme
Triton Theme

Conclusion

In this tutorial, I’ve explained how to migrate your Sencha Touch application to Ext JS 6 Modern toolkit. For me, the basic upgrade took a few hours, and the upgrade to MVVM took a morning. However, this is a pretty basic application with not many views.

Upgrading is easier than when you had to upgrade from Sencha Touch 1 to Sencha Touch 2, but it can take some time. It depends on whether you want to upgrade the pattern too, and if you have lots of custom components in your existing Sencha Touch app.

We have lots of professional services engineers, who migrate complex applications all the time, and they can help you with your application. Contact us for details.

Windows Theme

I do think it’s worth spending the time on upgrading your app with the MVVM pattern because:

  • You will be on the latest framework, and support the latest browsers and operating systems.
  • You can clean up your code base a lot.
  • The MVVM pattern can improve performance.
  • You can create desktop & mobile applications with one code base.
  • You will get all new classes, components, and themes.
  • You can use the new theme package structure, and compile themes much faster.

Because of the new Ext JS core, all newer Ext JS apps (version 5 and up) will be backwards compatible. That means it will be simpler to upgrade (just like Ext JS 5 to Ext JS 6 applications, which only require an upgrade through Cmd).

How to Upgrade a Sencha Touch App to Ext JS 6 Modern Toolkit – Part 2

Posted on in Ext JS 6 Sencha Touch

Cupertino Theme

In part 1 of this blog post series, I discussed the changes in Ext JS 6 Modern Toolkit and showed you how to do a basic mobile upgrade of your Sencha Touch app. In this article, I’ll show you how to do an advanced mobile upgrade.

Advanced Mobile Upgrade

For the advanced mobile upgrade, you will use the MVVM pattern. It will take more time and steps to upgrade this way, but you will have a lot of advantages with the latest framework and all of the new features and classes. Also, you can improve your application performance and code base with the new MVVM architecture.

I’ve cloned this dinmu1 folder to a new folder called dinmu2, so you can see the differences.

Start with Migrating the Views

  1. In the app/view folder, create the following folder structure (every view gets its own subfolder):
    1. app/view/main
    2. app/view/settings
  2. Move Main.js inside the main subfolder, and SettingsView.js into settings subfolder. (I also renamed SettingsView.js to Settings.js)
  3. Edit the namespaces for these two views to:
    1. Dinmu.view.main.Main
    2. Dinmu.view.settings.Setting
  4. At this point, you broke the app because the viewport can’t find Main.js and the Main.js view can’t find the Settings view, so you have to fix this:
    1. In the app.js, you can remove the line:
      Ext.Viewport.add(Ext.create('Dinmu.view.Main'));
    2. Above the launch() method, you create a new viewport, via the new way Ext 6 provides, by setting the mainView property to: mainView: 'Dinmu.view.main.Main',
    3. Remove the views: ['main'] from app.js
    4. Add 'Dinmu.view.main.Main' to the requires array
    5. In Main.js, change the requires for the Settings View to 'Dinmu.view.settings.Settings'
  5. To confirm that nothing breaks after this fix, you can run a sencha app refresh, and you shouldn’t see any errors.

    Files

Migrate the Controllers to View Controllers

  1. Create the following new file:
    app/view/main/MainController.js
  2. Create the following class definition:

    Ext.define('Dinmu.view.main.MainController', {
        extend: 'Ext.app.ViewController',
        alias: 'controller.main',
     
        //all the VC methods
        init: function(){
          console.log("new VC is initialized");
        }
     
    });
  3. Wire up the view controller to the main view:
    In Main.js, add the following line: controller: 'main',
  4. Also add the MainController to the requires array: Dinmu.view.main.MainController
  5. Run another sencha app refresh, and test the app in the browser. You should see a log message that states the wiring of the VC was successful. Note, you don’t need to wire this controller up to the Settings view. Because Settings view is nested inside the main view, it can always access the main controller.
  6. You can remove the controllers array from app.js, because you won’t use it anymore.
  7. Remove the init method from the view controller and copy over all the methods from app/controller/Main.js into the new view controller.
  8. Now comes the tricky part. You won’t use the refs and control blocks, so you need to fix these. Instead of the control block, you will create listeners in the view.

    There are 5 controls that need to be replaced:

    • onCarouselChange – activeitemchange in the main view
    • btnBack – tap back button in title bar
    • onSettingsBtnTap – tap settings button in settings view
    • onToggle – toggle on togglebutton
    • onRefresh – executed on tap of the refresh button

    In the Main.js view class, you will create the activeitem change listener:

    listeners: {
       'activeitemchange': 'onCarouselChange'
    },

    On the back button in Main.js, you will create a tap listener:

    listeners: {
       'tap': 'onBackBtnTap'
    },

    On the settings button in Main.js, you will create a tap listener:

    listeners: {
       'tap': 'onSettingsBtnTap'
    },

    On the toggle button in Settings.js, you will create a toggle listener:

    listeners: {
       'change': 'onToggle'
    },

    On the refresh button in Settings.js, you will create a tap listener:

    listeners: {
       'tap': 'onRefresh'
    },
  9. When you run the application in your browser, you will notice various event errors. The references with component queries are broken. You will fix these now.
  10. All the references to this.getMainView() can be replaced for this.getView(). Because the view controller now knows about the view, you can fix this one easily. I replaced it on 3 places.

    The other view references that you need will get a reference on the component, that you can look up later. In Settings.js, add the following property: reference: 'settings'.

    In the MainController, replace this.getSettingsView() with this.lookupReference('settings').

    You can fix the onToggle Method like this:

    var s = this.lookupReference('settings');
     
    if (!newVal) {
       s.down('field[name="city"]').enable();
       s.down('field[name="country"]').enable();
       s.down('field[name="units"]').enable();
    } else {
       s.down('field[name="city"]').disable();
       s.down('field[name="country"]').disable();
       s.down('field[name="units"]').disable();
       s.down('field[name="city"]').reset();
       s.down('field[name="country"]').reset();
    }

    In the Main.js view, put a reference in the titlebar configuration:

    reference: 'titlebar',

    Then replace the onCarouselChange method with:

    onCarouselChange: function(carousel, newVal, oldVal) {
       var t = this.lookupReference('titlebar');
     
       if (newVal.getItemId() == "mainview") {
          t.down('button[action=back]').hide();
          t.down('button[action=settings]').show();
          t.setTitle('Do I need my Umbrella?');
       } else {
          t.down('button[action=back]').show();
          t.down('button[action=settings]').hide();
          t.setTitle('Settings');
       }
    },

  11. Change the onLaunch method to init. Note, this will break the application because Dinmu.utils.Functions.loadData(), uses the Settings store, which is not wired up to a controller anymore. For now, comment the line with Dinmu.utils.Functions.loadData() out.
  12. Run another sencha app refresh and test the app in the browser. Everything except the refresh button should work. The refresh button requires the store, which is not linked yet.

Link the Store to a View Model

  1. Create the following new file:
    app/view/main/MainModel.js
  2. Create the following class definition:

    Ext.define('Dinmu.view.main.MainModel', {
        extend: 'Ext.app.ViewModel',
     
        alias: 'viewmodel.main',
     
        requires: [
     
        ],
     
        stores: {
     
        }
    });
    
  3. Wire up the view model to the the main view:
    In Main.js, add the following line: viewModel: 'main',
    Don’t forget to put the Dinmu.view.main.MainModel into the requires array.
  4. Now, link the Settings store; first add Dinmu.store.Settings to the requires array.
  5. In the Settings store, set an alias: 'store.settings' in the store class definition.
  6. In Ext JS 6, Stores don’t automatically set the storeId to the name of the class, therefore set the storeId to Settings, so the store manager can find the store via Ext.getStore('Settings')
  7. After that, add the following store to the stores object, (the type points to the settings alias):
  8. 'settings': {
       type: 'settings'
    },
  9. Enable the Dinmu.utils.Functions.loadData() line, which you commented out before in the MainController. Then run another sencha app refresh and test your app.
  10. At this point, you should have a working app that uses the MVVM pattern.

Other App Improvements

  • This application doesn’t use data feeds in the store. However, another big advantage with Ext JS 6 is that you don’t need to code all the model fields in your Model definition. It gets the data directly from the feed. That saves you from typing all the data in the feed, and makes your model definitions a lot smaller.
  • Another thing that’s different in Ext JS 6 is the config blocks. In Sencha Touch, you defined everything in the config block; in Ext JS 6, you only put properties in a config block that need the auto generation of getters, setters, apply, and update methods. For the Dinmu application this means that I had to remove most of the config blocks. For most of the classes, the config block in Sencha Touch style works fine, but you could run into weird problems at some point, if you leave them.
  • Promises and Deferreds support. I was always a bit amazed that the way I coded the saving of the settings form just worked. There’s a lot of magic going on in the sync() method, and the way they order the new created records, removed and edited records. It would have been a lot better, if I could have coded it this way:
    • Enter the form.
    • Check if localstorage contained old settings.
    • Remove old records, if any.
    • Sync store, and after the sync is complete, add new records.
    • Sync store, and after adding, load what’s in the store.

With Ext JS 6, you can do this because it supports promises and deferreds, which allows you to chain methods, via the then() method. Look at how I coded the removeAllSettings and addSettings methods. In the onRefresh method, I chained it. You can compare it with the dinmu1 or touchdinmu files to see how this code differs.

Upgrade the Theme

  1. You can switch themes by changing the theme property in the app.json file. Out of the box, you can choose between the following themes:
    • theme-cupertino (ios theme)
    • theme-mountainview (android theme)
    • theme-blackberry (blackberry theme)
    • theme-windows (windows theme)
    • theme-neptune
    • theme-triton (default)
    Cupertino Theme
    Triton Theme

    After switching the theme, you will need to run sencha app build.

  2. The platform switcher in Ext JS is renewed. Instead, you will now use the profiles build block in app.json. To set this up, write in app.json:
  3. "builds": {
      "ios": {
        "toolkit": "modern",
         "theme": "theme-cupertino"
      },
    
      "android": {
        "toolkit": "modern",
          "theme": "theme-mountainview"
      },
    
      "windows": {
        "toolkit": "modern",
        "theme": "theme-windows"
      },
    
      "bb": {
        "toolkit": "modern",
        "theme": "theme-blackberry"
      },
    
      "default": {
        "toolkit": "modern",
        "theme": "theme-triton"
      }
    },

    To enable the multiple themes on your development machine, add these lines to the app.json bootstrap block:

    "bootstrap": {
      "base": "${app.dir}",
     
      "microloader": "bootstrap.js",
      "css": "bootstrap.css",
     
      "manifest": "${build.id}.json" //this is the magic, which generates a manifest file, to load on local.
    },

    To enable the multiple themes on your production build, add these lines to the app.json output block:

    "output": {
       "base": "${workspace.build.dir}/${build.environment}/${app.name}",
       "appCache": {
          "enable": false
       },
       "manifest": "${build.id}.json",
       "js": "${build.id}/app.js",
       "resources": {
         "path": "${build.id}/resources",
         "shared": "resources"
        }
    },

    In index.html you write:

    Ext.beforeLoad = function (tags) {
        var s = location.search,  // the query string (ex "?foo=1&bar")
            profile;
    
        if (s.match(/\bios\b/) || tags.ios !==0) {
            profile = 'ios';
        }
        else if (s.match(/\bandroid\b/) || tags.android !==0) {
            profile = 'android';
        }
        else if (s.match(/\bwindows\b/) || tags.windows !==0) {
            profile = 'windows';
        }
        else if (s.match(/\bbb\b/) || tags.bb !==0 ) {
            profile = 'bb';
        }
        else {
            profile = 'default';
        }
    
        Ext.manifest = profile; // this name must match a build profile name
    };
    

    You will need to run sencha app refresh and sencha app build, which builds all profiles, to get it up and running.

  4. Themes for Ext JS 6 Modern toolkit use the same packages structure as Ext JS did. This is great, because it means that you can extend from your own theme packages, and you can generate custom themes with Sencha Cmd:
  5. sencha generate theme theme-MyTheme

Even if you don’t plan to create custom theme packages, theming is more advanced. To upgrade an existing theme, you have to put all the variables in the sass/var/ folder.

Take a look at my sass/var/all.scss which I used for the weather app application. The custom Sass / CSS classes will be stored in the sass/src/ folder. For an application (without custom theme packages), you have to map the folder structure of your JS applications. In other words, app/view/main/Main.js has a Sass file in this location: sass/src/view/main/Main.scss.

Mountainview Theme

I could take most of my styling directly from my Sencha Touch application. However, there is no “default” Sencha Touch theme anymore, instead there’s the Neptune & Triton themes, which both have different Sass variables and require different DOM.

This means that when you used custom styling for templates (tpls) etc, it won’t break in your upgraded app, but when you used custom Sass to override the Sencha Touch theme, you might see differences. The best practice is to manually go through all the views in your browser, and check to see if the styling is correct. Take a look at my sass/src/view/main/Main.scss which I used for the weather app application.

In the next article in this series, I will show you how to do an advanced universal upgrade.

How to Upgrade a Sencha Touch App to Ext JS 6 Modern Toolkit – Part 1

Posted on in Ext JS 6 Sencha Touch
Cupertino Theme

Previously, I wrote a blog post on how to create great looking universal apps with Ext JS.
However, we also have lots of customers who currently have a mobile (phone or tablet) application and want to upgrade it to Ext JS 6.

In this tutorial, I will show you how you can upgrade your app, and why you should consider taking this step.

I used my existing tutorial files, “Do I need my umbrella” weather application, which I wrote a couple of years ago with Sencha Touch 2. You can find the original tutorial here. You can download the tutorial files here.

You don’t have to use these tutorial files, you can also just read through this guide and try it out with your own existing Sencha Touch 2 app.

Ext JS 6 Modern Toolkit and Sencha Touch

Ext JS has more (advanced) classes and features than Sencha Touch. You can create advanced enterprise desktop applications, and now you can also create advanced mobile applications or even advanced cross-platform apps.

We incorporated concepts from Sencha Touch 2, and merged them as “the modern toolkit” in Ext JS 5, with the modern core (class system, mvvm pattern, etc.), and there are also many updated classes. From a theming perspective, Ext JS 6 modern toolkit has been updated and looks different than Sencha Touch.

When you’re looking for an enterprise solution to create mobile apps, whether it’s a universal app or just mobile, there are many reasons why you’d choose Ext JS 6 Modern toolkit. I will explain these benefits to you in this article.

Then, I will take an example Sencha Touch 2 application, and migrate it to Ext JS 6 with the Ext JS 6 Modern toolkit.

What’s Different in Ext JS 6 Modern Toolkit

Here’s an overview of new features in Ext JS 6 compared to Sencha Touch.

Basic Upgrade

(No change to the MVVM pattern)

This upgrade allows you to use:

  • the latest mobile framework version, and support for the latest OS & browser versions
  • running your mobile application on your desktop computer too
  • controlling lists with your mouse scroll and keyboards (besides touch support)
  • new packages / theme packages structure
  • new Neptune and Triton (universal) themes
  • fast theme compilation with Fashion
  • cleaning up your models, by writing less code
  • JavaScript promises, for asynchronous code
  • out-of-the-box font-awesome integration
  • one of the new components/classes:
    • data grid
    • data tree
    • navigation tree list
    • soap, amf0, amf3 proxies
    • new charts
    • form placeholders

Advanced Upgrade

(Change to MVVM architecture pattern)

This upgrade allows you to use:

  • ViewControllers and ViewModels
    • The Stores and Controllers in MVC are global. VCs and VMs live together with a particular view, which means that they will be created with a view, and can be destroyed. ViewModels and ViewControllers therefore can improve your application performance. They also allow you to write less code and make it easier to maintain.
  • Databinding
    • Bind to data or component states. It allows you to do advanced things by writing less code.

Universal Upgrade

This upgrade allows you to:

  • Create cross-platform apps, for mobile phones and tablets, but also desktop computers. By supporting the modern (lightweight component set) and the classic rich desktop component set.
  • Support legacy browsers, like Internet Explorer 8, as well as the latest modern (mobile) browsers.

Things That Changed in the API

You can read a complete list of Ext JS 6 API changes here. The ones that I faced when upgrading the weather utility app are:

  • ViewControllers and ViewModels
    • The Stores and Controllers in MVC are global. VCs and VMs live together with a particular view, which means that they will be created with a view, and can be destroyed. ViewModels and ViewControllers therefore can improve your application performance. They also allow you to write less code and make it easier to maintain.
    • Sencha Touch has Ext.app.Controller.launch() methods; in Ext 6 Modern toolkit, it’s Ext.app.Controller.onLaunch()
    • In Sencha Touch, you had to define everything in a config block; in Ext 6 Modern toolkit, you just put properties in config blocks that need the magic methods (get, set, apply, and update). Although you don’t have to, you can clean up the config blocks.
    • There are changes in the way you wire up stores that you can read about in these docs:
    • Sencha Touch validations are now called validators
    • The Sencha Touch default theme was replaced by Ext JS 6 Modern toolkit themes – Neptune and Triton.
    • The default icon set that is being used is Font Awesome, instead of Pictos.

    Basic Mobile Upgrade

    For the basic, easy upgrade, we will stick with the existing MVC pattern. You will see that it won’t take many steps. However, you won’t be taking advantage of Ext JS 6. You will have the latest framework, with all its features and classes, but you won’t be using the new MVVM pattern.

    1.  Download the Ext JS 6 (trial version).

    2.  Look in your Sencha Touch project (app.js for example), and note the namespace that was used. For example, for the Weather Application, the namespace is “Dinmu”.

    3.  Generate an Ext JS 6 modern app:

    Navigate to the ext framework folder, and generate a project with:
    sencha generate app -modern
    For example:
    ext> sencha generate app -modern Dinmu ../dinmu1

    See https://github.com/savelee/ext-weatherapp/tree/master/dinmu1

    4.  Go to the project in your browser, you should see the new Ext JS 6 demo app.

    5.  In your file system, rename the <myproject>/app folder to something else (like app-backup)

    6.  Do the same for the app.js file; rename it to app-backup.js

    7.  Then, copy the app folder and the app.js from your Sencha Touch project, and paste it in your new Ext JS 6 project.

    In case you are loading external JS or CSS files via app.json, you can manually merge those lines into the new app.json. My advice is to do these kind of steps at the end, after you have your app running.

    8.  Run the following command from the command-line:

    1. sencha app refresh
    2. You might run into build errors here, because of API changes. For the Dinmu app, there was an error because Ext.device.Geolocation has been deprecated.
    3. When you have lots of custom components, you may run into problems here. The best way to solve them is to read the messages from the CLI, and open the Modern toolkit API docs to search for the classes that fail. In my case, it was the geolocation class that failed. In the docs, I noticed that there are no device APIs anymore. In Sencha Touch, these classes where wrappers for PhoneGap/Cordova support, that would fall back to the HTML5 API feature, if available in the browser. There is Ext.util.Geolocation, so I changed the code to use it. After I changed the line, I ran another sencha app refresh again, to check for more errors. See the results here.

    9.  When you don’t have any more errors anymore, you can try to run the application in the browser. When I ran my app, I got a console error in my app.js launch method.
    Ext.fly(‘appLoadingIndicator’).destroy();

    Basically, this is an error that tells you that you can’t destroy the “appLoadingIndicator” element, just because it’s not there. The index.html is just different. Now you don’t want to replace the index.html file, with the Sencha Touch one, because the calls to the microloader are different. It’s up to you, if you want to remove this destroy line in the app.js launch method, or if you take over the <style> and <body> tags from the Sencha Touch app. I liked the Sencha Touch simple CSS preloader, that you will see before loading any JS or CSS, so that’s why I took over those tags. After fixing this problem, I was able to open my Ext JS 6 app in the browser.

    10.  The application is running a bit odd. By inspecting my application, I noticed that in my Sencha Touch application I have controllers with launch methods. And launch methods on controllers don’t exist in Ext JS 6, instead they’re called: onLaunch. So I renamed it, and ran the application again.

    11.  This time I had a problem with the store. The store manager couldn’t find Ext.getStore('Settings'), because it was wired up to the controller like this: Dinmu.store.Settings. Instead, the store manager has to access it via the full class name. I fixed it in the controller, instead of wiring up the full path, and I just passed in the Store name.

    12.  The settings button was not visible; this was due the changes in the icon sets. I used the default font-awesome settings icon, and changed the iconCIs in the Settings button in Main.js to: x-fa fa-cog

    Settings

    13.  Last step was to run a build to make sure that I was able to build my application. I expected it to work, because the sencha app refresh command did not fail.

    And that’s it. After this last step, I was able to run the Weather Application as a full working Ext JS 6 mobile app.

    Coming Up Next

    In the next article in this series, I’ll show you how to do the advanced upgrade, where we will switch to the new MVVM pattern, and we can also clean up some code.

How to localize your Sencha Touch applications

Posted on in Sencha Sencha Touch

I live in Europe; in Europe they speak about 23 languages. In some countries it is even common to speak more than 2 or 3 languages. Especially for these countries localisation of applications and websites is very important.

So you need to come up with a strategy on how to localize all your views.
In Sencha Touch localization works a little different than in Ext JS, since there are no packages; but overall the basic idea is the same:

“All your views shouldn’t contain text literals, but variables.” and “all your views are built dynamically.
You will create a view class override, to “override” the variables with language translation.

Ext.define('MyApp.view.Main', {
    extend: 'Ext.tab.Panel',
    xtype: 'main',
    requires: [
        'Ext.TitleBar',
        'Ext.Video'
    ],
    TAB_ONE_TITLE_SHORT: 'Hello',
    TAB_ONE_TITLE: 'Hello Sencha Touch 2',
    TAB_ONE_HTML: 'This app was written in English.',
    config: {
        tabBarPosition: 'bottom',
    },
    initialize: function() {

        var items = [{
                title: this.TAB_ONE_TITLE_SHORT,
                iconCls: 'home',

                styleHtmlContent: true,
                scrollable: true,

                items: {
                    docked: 'top',
                    xtype: 'titlebar',
                    title: this.TAB_ONE_TITLE
                },

                html: this.TAB_ONE_HTML
            }
        ];

        this.add(items);
        this.callParent();
    }
});

I uploaded my code to Github:

https://github.com/savelee/hands-on-sencha-touch-2/tree/master/99-Other/Localization

When you download and preview this code, it doesn’t look much different than an auto generated app by Sencha Cmd, right? Well the difference here, is that this view is build dynamically try this out.

Note the initialize: function(). Instead of coding the items in the config object, we’re creating a variable items, which is an array that contains all the items and are added later to the view. The text literals are not directly written; instead we are pointing to the new class variables: this.TAB_ONE_TITLE, this.TAB_ONE_TITLE_SHORT and this.TAB_ONE_HTML.

Nice! So these are the variables which needs an override, to replace these with different language translations. But how do we do that?

Well let’s create a new folder in the app directory first: “utils”.
In this folder, you can create another folder, with the name of your language translation and within that folder, you can create the same folder structure as your view directory, (or keep it one single file).

For this example, I’m using Dutch translation; so my path will look like: app/utils/nl/Main.js
Here’s the override class:

Ext.define('MyApp.utils.nl.Main', {
    override: 'MyApp.view.Main',

    TAB_ONE_TITLE_SHORT: 'Hallo',
    TAB_ONE_TITLE: 'Hallo Sencha Touch 2',
    TAB_ONE_HTML: 'Deze app is geschreven in het Nederlands.',
});

As soon as it loads this file, it will override the previews defined Main view.
Ok, so now we have a dynamic view and a view override with language translations. How do you load this in your app? Just add it to the requires!

Open app.js, and add the language class there:
requires: [‘MyApp.utils.view.nl.Main’]

That did the trick, the app is now successfully localized to Dutch!

Great, but what if I want to create a dropdown with all different languages, and let the user select a language?

You could do this, with for example an Ext.Ajax request, or with Ext.require(), but you will need a hard refresh. When this hard refresh happens it needs to know which language it needs to load.
We can’t save this in the memory because that will be gone during a hard refresh; but we could save it for example in a cookie or browser (local) storage.
You do need to delay the creation of your application, because the call for the language file will be returned in a callback…

The code for loading should be something like this:

app.js:

    launch: function() {
        onCallback = function(){
            Ext.Viewport.add(Ext.create('MyApp.view.Main'));
        }

        Ext.require(localStorage.getItem('language'), onCallback);
    }

For my demo I created a Toggle pirate language button; this button sets the localstorage and refreshes the page:

{
docked: 'top',
xtype: 'toolbar',
items: [{
    xtype: 'button',
    text: 'Toggle pirate language',
    handler: function(){
        if(localStorage.getItem("language")) {
            localStorage.removeItem("language");
        } else {
            localStorage.setItem("language", "MyApp.utils.pirate.Main");
        }
        window.location.reload();
    }
}

With this pirate language file:

app/utils/pirate/Main.js

Ext.define('MyApp.utils.pirate.Main', {
    override: 'MyApp.view.Main',

    TAB_ONE_TITLE_SHORT: 'Ahoy!',
    TAB_ONE_TITLE: 'Ahoy! Sencha Touch 2',
    TAB_ONE_HTML: 'Tis app be written in scurvy pirate language, matey!',
});

And that’s the trick!

Update 2016:

Sencha partners: Jnesis, wrote a very nice blog post on how to deal with localization for Ext JS 6, where you don’t have to deal with page refreshes. Please have a look: Blog Post

Does Sencha Touch support Windows 8?

Posted on in Questions Sencha Touch

Yes, Sencha Touch 2 supports Windows Phone 8.1, Microsoft Surface Pro and RT. Actually, Sencha Touch 2.2 and up even supports Internet Explorer 10 and Windows 8.

That also means support for tablets running on Windows 8, IE10 and up.
Mind you we have very nice out of the box themes for Windows Phone!

Please see:
http://www.sencha.com/products/touch/features/
http://www.sencha.com/blog/sencha-touch-with-windows-phone-8/]]>

(It's probably similar for Ext JS 6 Modern toolkit and up.)

Some Sencha news from me!

Posted on in Ext JS 5 Sencha

Hi guys,

I just wanted to share some personal Sencha updates with you!

Hands-on Sencha Touch 2 - O'Reilly

First of all, my book "Hands-on Sencha Touch" is finally printed.
I spent a lot of time, discussing the latest Sencha Touch framework and with this book it's possible to build mobile web applications.
Checkout the table of contents at: http://shop.oreilly.com/product/0636920030058.do

If you like my writing style. I am developing ideas for writing an advanced Ext JS 5 book!

Ext JS 5 courses

Talking about Ext JS 5, the new Sencha Ext JS framework... I've been very busy lately, developing course materials for various Ext JS 5 beginners & advanced courses. Learn Ext JS 5, the new MVVM application architecture (viewcontrollers + databinding woot woot!), how to upgrade to Ext JS 5 or how to develop huge enterprise apps for tablets with Ext JS version 5.

Checkout our training schedule: http://www.sencha.com/training/
I will be teaching across all over Europe the next coming months:
London, Paris, Frankfurt, Munich, Milan, Zurich, Amsterdam and of course Live Online!
Interested? Leave a comment below, and I can give your some discount promo codes!

Conferences & Workshops

For the rest I'm presenting lately on a lot of workshops and conferences.
Tomorrow I will host another appcamp for Appsterdam:
http://www.meetup.com/Appsterdam/events/184318382/
Come join and check this out!

Also I will host a webinar for O'Reilly. Add the date to your calendar:
http://www.oreilly.com/pub/e/3100

Simple Techniques for Solving Common Sencha Coding Problems

Often when I’m teaching a Sencha Training class, students ask me to look at their apps because there’s a problem they don’t know how to fix. Since I didn’t write the code, it’s hard sometimes for me to give them a quick answer. However, I do have a set of simple techniques that filter out the most obvious problems.

In this tip, I’ll categorize a couple of most common problems and tackle them with some simple but effective strategies.

Problem: “I don’t see my data”

You are browsing through your app, but the data is not visible. Often, this problem is easy to fix.

“Here, try this:”

First, try to inspect the Store. You can do this from the browser console by running:

Ext.getStore(‘MyStore’).load();

This returns the Store object. You can drill through the data config and see if the array length is greater than zero.

If there is data available, something probably went wrong with rendering. Consider these possible issues:

Do the data fields map the fields in the Model?

Is the data array empty? In your browser developer toolbar, hit the Network tab. Do you get a status code 200? No? Then something went wrong with your request. Check your Model/Store proxy.

The request works correctly, but it still doesn’t display the data? Verify whether the data you get back is valid. For example, when you are using JSON data, you can copy the data response from the browser network tab into http://jsonlint.com or http://jsonplint.com/. You can also use your own written test data too.

Problem: “I can’t build my app”

Sencha Cmd won’t build your app. Most of the time, Sencha Cmd gives a clear explanation of what’s going on, or what needs to be changed. However, every now and then, I see problems where Sencha Cmd won’t build. and the error description is not clear. It might be that there is nothing wrong with your code. For example, your code runs perfectly on your local environment. It just won’t build.

“Here, try this:”

This trick is pretty radical, but most of the time it works. Generate a new application with the same namespace from the command line:

sencha generate app App ../myapp

Next, copy over the app folder, and make sure you take the changes over from app.js. Now try it again!

Problem: “Strange component-x behavior”

These types of problems are always the hardest ones. For example, suddenly multiple scrollbars show up in your grid. Or, you see a tab panel with the wrong styling. Testing these kind of problems within your app can be time consuming. Not only do you have to navigate through your app to get to this problem, there can also be many reasons why it’s broken.

“Here, try this:”

A common problem-solving technique for developers is to isolate the problem into smaller, more manageable chunks.

Isolate the problem

Let’s generate a new application with Sencha Cmd, again with the same namespace. Now, copy over the Class that contains the problems and test it. Do you see the same bugs? You can try to solve it in this test app. You can isolate it even further by trying to re-build your class from the ground up. Start with only the necessary code.

Did it work? There is nothing wrong with the framework, and there is nothing wrong with this Class. Something else must be wrong.

Switch to the default theme

Go back to your own app and try to switch to one of the Sencha default stylesheets. (Sencha Default StyleSheet in Sencha Touch, Neptune Theme in Ext JS) Does it finally work? Then there is something wrong in your custom StyleSheet. Is it still not working? At least now you know that your custom StyleSheet is correct. There might be something wrong with your nesting. Or maybe you used the wrong layout?

Query for Components

Do you have problems with querying for Components? You can easily query components from your browsers dev console:

Ext.ComponentQuery.query('button[action=”test”]');

Does it return an empty array? Then there you go! Or maybe it does return the components, but you made a timing mistake. That can often be the case when you’re working with callbacks. When your code is executed, the component may not be rendered on the screen.

Common Debugging Techniques

As a developer, you will often run into bugs and problems that you have to solve. But hey, that’s what makes our jobs challenging, right?

Aside from the above mentioned techniques, there are also a couple of standard tricks. First of all, know the framework and know your tools. Read the API Docs (or even better, browse through the framework code).

Switch to one of the debugging frameworks. The advantage is that it often shows extra log messages, and you can directly read through the framework code. For Sencha Touch projects, open app.json and change the framework temporarily:

"js": [
{
"path": "../touch/sencha-touch-all-debug.js",
"x-bootstrap": true
},

For Ext JS projects, open index.html and change the framework temporarily:


Your browser dev tools can help (Google Chrome or Firebug). Also, there are some handy plugins for developing Sencha code: Illuminations and App Inspector for Sencha.

Do you quickly want to prototype something? Try Sencha Fiddle. There are great tools for testing available, such as Siesta.

And last but not least, if none of these techniques help you and you are staring at your code for hours (or even days)... take a break! Often, when you take a break and free your mind, you can solve it right away. Especially if you’ve made spelling mistakes or (case sensitive) typos that can cause hours of frustration because you just don’t see them.

Looking for more help? Check out one of the Sencha Ext JS and Sencha Touch training classes located around the world, or join an online class.

How to Set Up Your Sencha Environment

Posted on in Sencha

While teaching Sencha app camps and training classes, every now and then I see common app build problems related to the installation of the Sencha environment. It’s important to understand the dependencies to get yourself up to speed. In this article, I’ll provide an overview of the dependencies and show you how to get everything set up correctly.

Getting Started

Let’s take a look at the dependencies, in order to use Sencha Cmd as a build and code generation tool, you will need to have the following setup, as a base:

  • Java Runtime Environment
  • Ruby
  • Sencha Cmd
  • Sencha Frameworks

Java, Ruby and Sencha Cmd must be available from the command line to use these features. When installing Java, Ruby or Sencha Cmd, usually the installer will add it to the PATH system variable. However, sometimes these variables get lost or were not added at all. When that’s the case, these tools are not available on the command line, so Sencha Cmd can’t access them. It’s very important that these paths are set, so let’s look into how to set the system path variable. If you know this process, you can skip the next paragraph.

How to Set a System Variable

I will explain how to add a variable to the PATH on different systems. Later in this article, I will discuss the variables and paths to set.

Windows

  • Windows XP
  • Windows Vista
  • Windows 7
  • Windows 8

Mac OSX / Linux

  • Bash shell

Windows XP

  1. Start -> Control Panel -> System -> Advanced
  2. Click on Environment Variables, under System Variables, find PATH, and click on it.
  3. In the Edit windows, modify PATH by adding the location of the class to the value for PATH. If you do not have the item PATH, you may select to add a new variable and add PATH as the name and location of the class as the value.
  4. Close the window and reopen the command prompt window.

Windows Vista

  1. Right click My Computer icon
  2. Choose Properties from the context menu
  3. Click Advanced tab (Advanced system settings link in Vista)
  4. In the Edit windows, modify PATH by adding the location of the class to the value for PATH. If you do not have the item PATH, you may select to add a new variable and add PATH as the name and location of the class as the value.
  5. Close the window and reopen the command prompt window.

Windows 7

  1. Select Computer from the Start menu
  2. Choose System Properties from the context menu
  3. Click Advanced system settings > Advanced tab
  4. Click on Environment Variables, under System Variables, find PATH, and click on it.
  5. In the Edit windows, modify PATH by adding the location of the class to the value for PATH. If you do not have the item PATH, you may select to add a new variable and add PATH as the name and location of the class as the value.
  6. Close the window and reopen the command prompt window.

Windows 8

  1. Drag the Mouse pointer to the Right bottom corner of the screen
  2. Click on the Search icon and type: Control Panel
  3. Click on Control Panel > System > Advanced
  4. Click on Environment Variables, under System Variables, find PATH, and click on it.
  5. In the Edit windows, modify PATH by adding the location of the class to the value for PATH. If you do not have the item PATH, you may select to add a new variable and add PATH as the name and location of the class as the value.
  6. Close the window and reopen the command prompt window.

Mac OSX / Linux

  1. Edit the bash profile (~/ .bash_profile)
  2. Modify PATH variable, write the following line, with the path to one of the tools:
    1. export PATH=<PATH-TO-ADD-HERE>:$PATH
  3. Save and close the file and open a new terminal window

NOTE: The .bash_profile is a hidden file, to enable hidden files in Finder, run the following command from the command line:

defaults write com.apple.finder AppleShowAllFiles TRUE
killall Finder

Java Runtime Environment

Java Runtime Environment is required by the build tools of Sencha Architect (Sencha Cmd). You will need a valid build to display your app stylesheet, so it’s necessary to have Java installed.

To check if you have Java running, type the command below from the command line. (Mac OSX users, open the terminal, Windows open the command line by entering cmd from the start screen.)

java -version

If correctly installed, it should output the version number. For example:

>java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)

The JRE is the Java Runtime Environment. It’s an implementation of the Java Virtual Machine which actually executes Java programs. Without JRE. you can only compile the application but you can’t run it.

The JDK is the Java Development Kit. It’s a software bundle that you can use to develop Java based software. Since JRE contains the JVM which executes the byte code generated from the javac compiler, you need to add your JRE path to JAVA_HOME variable from the environment variables.

Note: the JDK contains the JRE, so if you have set your PATH properly you shouldn't need a separate entry for the JRE.

You can download Java JRE 1.7 or the JDK.

Windows users:

Run these commands from the command line to add Java to your PATH:

variable name:
JAVA_HOME
variable value:
c:jdk1.7.0_40
variable name:
PATH
variable value:
%PATH%;%JAVA_HOME%bin

Mac OSX / Linux users:

Assume Java is installed in /Library/Java/JavaVirtualMachines/<java version>/. Run these commands in your terminal to add Java to your PATH:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_40.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH

For more information see: http://java.com/en/download/help/path.xml

Ruby

Sencha Architect uses Ruby during the app build process when building a theme. Theming in Sencha frameworks requires Sass & Compass. You don’t need to install those two dependencies since they ship with Sencha Cmd and Sencha Architect, but Sass & Compass run on top of Ruby, so Ruby is required.

To check if Ruby is correctly installed, run the command below from the command line. (Mac OSX users, open the terminal, Windows open the command line by entering cmd from the start screen.)

ruby -v

If correctly installed, it should output the version number. For example:

> ruby -v
ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13]

Ruby is automatically installed on Mac OSX machines. Windows users will have to download Ruby. Sencha Architect works with both Ruby 1.9 and Ruby 2.0 versions.

You can download Ruby.

Make sure you run the Ruby installer with admin rights (right click on the installer executable and select run as administrator.) During the installation, you will have to check the checkbox which asks to add Ruby to your PATH variables.

Sencha Cmd

To build applications with Sencha Architect, it requires the build tools, Sencha Cmd. Since Sencha Architect runs on top of Sencha Cmd, you don’t need to install Sencha Cmd because it’s included with Sencha Architect.

Sencha Cmd is a very useful set of tools. You can not only build your applications with it, you can also build themes, generate code or use the built-in (Jetty 8.1.7) web server.

You can test if Sencha Cmd is available from the command line by entering the following:

sencha which

If correctly installed, it should output the version number. For example:

> sencha which
Sencha Cmd v5.0.0.116
/Users/leeboonstra/bin/Sencha/Cmd/5.0.0.116/

It requires that Sencha Cmd is added to your PATH variables. This should happen automatically when installing Sencha Architect or Sencha Cmd. If it’s not available, you can download and reinstall Sencha Cmd:, or you can add the paths manually on the command line:

Windows users:

Assume Sencha Cmd is installed in c:senchacmd5.0.0.116.

variable name:
PATH
variable value:
%PATH%;c:senchacmd5.0.0.116

Mac OSX / Linux users:

Assume Sencha Cmd is installed in ~/bin/sencha/cmd/5.0.0.116.

export PATH=~/bin/Sencha/Cmd/5.0.0.116:$PATH

The build tools also need to be enabled in Sencha Architect. Verify Sencha Cmd is enabled by navigating to Settings > Project Settings Framework:

Sencha Frameworks

Check out the following Sencha product pages, to download the latest downloads for Ext JS or Sencha Touch.
Sencha Touch, Sencha's framework to create multi-device/mobile apps is free to use, and can be found here:
http://www.sencha.com/products/touch/. Ext JS is Sencha's framework to create desktop/tablet web applications with, for more information take a look into the product page at: http://www.sencha.com/products/ext/.

In case you have questions about your Sencha setup, feel free to comment underneath this post!

Ext JS 6

Update:
I wrote a new setup guide for Ext JS 6 development. Please check this link:
http://se.sencha.com/setup-guide/

Save 50% on Hands-on Sencha Touch 2 ebook today

Posted on in Sencha Touch

Today, O'Reilly has an unique deal, to save 50% on all 8000+ Ebooks & Videos in celebration of Day Against DRM.

This includes the book I wrote for O'Reilly: Hands-on Sencha Touch 2.  Use the following PROMO code for the ebook version: DRM2014

http://shop.oreilly.com/product/0636920030058.do

Deal expires May 7, 2014 at 5am PT, and cannot be combined with other offers or applied to Print, or "Print & Ebook" bundle pricing.

 

More about Day Against DRM

Having the ability to download files at your convenience, store them on all your devices, or share them with a friend or colleague as you
would a print book or DVD is liberating, and is how it should be.

Learn more about Day Against DRM (http://www.fsf.org/news/may-4-day-against-drm)

At O'Reilly Media, we've always published our ebooks DRM free, following the advice of Lao Tzu, who said, 2500 years ago, "Fail to honor people, they fail to honor you." --Tim O'Reilly, Founder

 

Create dynamic Sencha models from your server-side

Posted on in Ext JS Sencha Sencha Touch

Every now and then I get this question in my Sencha training classes: "How can I dynamically create Sencha Models from my server-side?", or "How can I dynamically inject fields?" Normally you would define a Sencha Model like this:

Ext.define('App.model.MyModel', {
  extend: 'Ext.data.Model',
  
  fields: [{
     name: 'id',
     type: 'int'
  }, {
    name: 'firstname',
    type: 'string'
  }, {
    name: 'lastname',
    type: 'string'
  }]

});

The previous code is a Model class definition written in Ext JS. In Sencha Touch, it's almost the same, you would wrap the fields array in a config object. Defining Models this way, is perfect, but sometimes you would like to generate your Models from the server-side. For example, because you are using lots of fields, field names often change and you don't want to maintain the fields on two places (server-side vs. client-side). Mind you, also the data-type or field validations, needs to be in sync on both places, to not experience funny behavior.

So? Is it possible to create dynamic models? How does that work?

Let's say we have a PHP & MySQL server-side. I'm not gonna show you my PHP skills, since it has been a while. (..but if you are really curious, please leave a comment, then I can see if I can share some codes). But you will need to request the database schema. With MySQL I could write the following SQL statement: SHOW COLUMNS FROM mytable, where mytable is my database table name. This will return an Array with all my database fields.

The next step is to output JSON. I only care about the field names, and the field types. But... the MySQL data-types are different then the data-types in Ext JS / Sencha Touch, so I somehow need to map a varchar to a string etc. After that's done, my JSON output should look something like this:

{
  success: true,
  fields: [{
    name: "id",
    type: "int"
  },{
    name: "fname",
    type: "string"
  },{
    name: "lname",
    type: "string"
  }]
}

Now we are getting somewhere. These are the fields I dynamically want to inject in my Sencha Model. I can do this with an Ext.Ajax.request. Take a look:

Ext.define('App.store.MyStore', {
  extend: 'Ext.data.Store',
  
  constructor: function(){
      var me = this;
      me.callParent();

      Ext.Ajax.request({
        url: '../data/phpscript/?action=schema',
        success: function(response) {
          try{
            var resp = response.responseText;
            if(resp) {
              var data = Ext.JSON.decode(resp);

              var model = Ext.define("App.model.MyModel", {
                  extend: "Ext.data.Model",
                  fields: data.fields
              });

              me.model = model.$className;
            }
          }catch(e){
            console.error(e);
          }
        },
        failure: function(e){
          console.error(e);
        }
    });
  }
});

Here is what I did. I defined a Store, in the constructor I run an Ajax request, which fetches the fields array from my backend script, (in my case:) ../data/phpscript/?action=schema, which returns the JSON. In the success method, I create a model, and that's where I inject the fields.

Alright. Now hook up the Store to your app and test. You can run in your browser console the following line:

Ext.create('App.model.MyModel', { lname: "Boonstra" });

That should work, it will return the record, and you will see all the (empty) fields that this record contains.

Now that you get the idea, you will be pleased to know, that you can use similar tricks for injecting validations from the server-side or dynamically injecting grid columns... Woot woot.