2014년 12월 7일 일요일

Training Tip: Simple Techniques for Solving Common Coding Problems

April 17, 2014 | Lee Boonstra

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 the 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.
Training Tip
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).
Training Tip
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, openapp.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 classeslocated around the world, or join an online class.

2014년 12월 5일 금요일

Performance Tip

Creating Instances on the Prototype is Bad

by Mitchell Simoens
When defining a new class using Ext.define, you should never use Ext.create to create an instance on the prototype like this:
 
Ext.define(‘MyApp.view.Main, {
    extend : ‘Ext.container.Container,
    xtype  : ‘myapp-main’,
 
    requires : [
        ‘MyApp.plugins.Foo],
 
    items : [
        Ext.create(‘Ext.Component, {
            html : ‘Hello’
        })
    ],
 
    plugins : [
        Ext.create(‘MyApp.plugins.Foo)
    ]
});
 
Instead, you should use configuration objects with a class alias:
 
Ext.define(‘MyApp.view.Main, {
    extend : ‘Ext.container.Container,
    xtype  : ‘myapp-main’,
 
    requires : [
        ‘MyApp.plugins.Foo
    ],
 
    items : [
        {
            xtype : ‘component’,
            html  : ‘Hello’
        }
    ],
 
    plugins : [
        {
            ptype : ‘myapp-foo’
        }
    ]
});
 

2014년 12월 3일 수요일

Do’s and Don’ts when creating an Ext extension

1. Follow Ext JS coding patterns

var width = 100,
height = 40,
area = 0;
if (doCalculate) {
    area = width * height;

}

2. Design classes for configurability

MyTip = Ext.extend(Ext.Tooltip, {
    fadeDuration: 200,
    onMouseLeave : function(){          this.el.fadeOut(this.fadeDuration);
    }
}

3. Make key functionality easily overridable

initComponent : function(){
    if (!this.tpl) {
        this.tpl = new Ext.XTemplate(
            '
{foo}
     );
    }
   
    // ....
}

4. Make classes localizable

MyClass = Ext.extend(Ext.Toolbar, {
    noDataText : 'No data to display’,
   
    constructor: function() {
        this.add({
            text : this.noDataText
        });
    });
});

5. Use a syntax checker

6. Clean up after yourself

MyPanel = Ext.extend(Ext.Panel, {
    constructor: function() {
        this.someEl = new Ext.Element();
    },
    onDestroy: function() {
        this.someEl.destroy();
        // Call superclass destroy method...
    }
});

7. Define an xtype

MyPanel = Ext.extend(Ext.Panel, {
    constructor: function() {
        // ...
    }
   
});
Ext.reg(’mypanel’, MyPanel);

8. Document your extension
/**
 * @class MyClass
 * @extends Ext.Panel
 * @constructor
 * @param {Object} config The cfg object
 */
MyClass = Ext.extend(Ext.Panel, {
    // ...
});

9. Test edge cases

Create an analog clock extension - Stpe by step

Step Step 1 – Choose a suitable base class

* We want to be able to use the clock inside a Panel or Window etc. 
=> Ext.Component.

* We want the clock to be able to have any size
=> Ext.BoxComponent


* We don’t really need support for toolbars, headers, buttons etc. 
=> Ext.Panel.

Introduction to Ext.BoxComponent

* Base class of most UI widgets in Ext JS (GridPanel, TabPanel, TextField etc...)
* Base class for any Component that is to be sized as a box, using width and height.

Ext.Component Life Cycle & Template Methods

* Initialization (constructor, initComponent)
       - Configuration, setup etc...
* Rendering (onRender, afterRender)
  - Add additional elements and styling here
* Destruction (onDestroy)
        - Clean up after yourself, destroy elements etc.


Step 2 – Create folders and a simple skeleton

Step 3 – Create a simple skeleton with stubs
Ext.ns('Ext.ux');
Ext.ux.Clock = Ext.extend(Ext.BoxComponent, {
    afterRender : function() {
        // Call superclass
        Ext.ux.Clock.superclass.afterRender.apply(this, arguments);
    },

    onDestroy : function() {
        // Call superclass
        Ext.ux.Clock.superclass.onDestroy.apply(this, arguments);
    }
});

Step 4 – Create simple example HTML Page
   
        
        ...
       
   

Step 5 – Create elements
afterRender : function() {   // The component is now rendered and has an ’el’
    var size = Math.min(this.getHeight(), this.getWidth());
            
    // Background image of an empty clock with no hands
    this.bgEl = this.el.createChild({
        tag : 'img',
        cls : 'ext-ux-clock-img',
        src : this.clockBgUrl,
        width : size,
        height : size
    });
    // Initialize a Raphael canvas for drawing the hands
    this.canvas = Raphael(this.el.dom, size, size);
   
    this.drawHands();
    this.on('resize', this.handleResize, this);
    this.timer = setInterval(this.drawHands.createDelegate(this), 1000);
    Ext.ux.Clock.superclass.afterRender.apply(this, arguments);
}

Step 6 – Draw hands
drawHands : function() {
    var size = Math.min(this.getHeight(), this.getWidth())
        date = new Date(),
        secs = date.getSeconds(),
        mins = date.getMinutes(),
        hrs = date.getHours(),
        canvas = this.canvas;
    canvas.clear();
    canvas.path(...);      // Draw minute hand
    canvas.path(...);      // Draw hour hand
    canvas.path(...);      // Draw second hand
}

Step 7 – Use a background image

Step 8 – Polish with CSS3
.ext-ux-clock-img
{
    border:3px solid lightgrey;
    -moz-border-radius:100%;
    -webkit-border-radius: 100%;
    -o-border-radius: 100%;
    border-radius: 100%;
    -moz-box-shadow:1px 1px 13px rgba(114, 114, 114, 0.8);
    -webkit-box-shadow:1px 1px 13px rgba(114, 114, 114, 0.8);
    -o-box-shadow:1px 1px 13px rgba(114, 114, 114, 0.8);
    box-shadow:1px 1px 13px rgba(114, 114, 114, 0.8);
    background:#222333 url(../images/glow.png) no-repeat center center;
}

Step 9 – Resize Support
handleResize : function(me, newWidth, newHeight) {
    var size = Math.min(newWidth, newHeight);
       
    this.bgEl.setSize(size, size, true);   // true to animate
    this.canvas.setSize(size, size);       // Resize Raphael canvas
    this.drawHands();       // Clears canvas and redraws
}

Step 10 – Don’t forget to clean up after yourself!
onDestroy : function() {
    clearInterval(this.timer);
   
    this.canvas.clear();
   
    Ext.destroy(this.bgImg, this.innerEl);
   
    // Call superclass
    Ext.ux.Clock.superclass.onDestroy.apply(this, arguments);
}

align & pack configuration property

align configuration property
• Controls how items are aligned
• HBox:
• top, middle, stretch, stretchmax
• VBox:
• left, center, stretch, stretchmax

pack configuration property
• Controls how items are packed together:
• start, middle, end

Layout 특징

Auto Layout
• AutoLayout is the default layout
• This layout is relatively dumb
• Uses HTML to naturally size items
• Does not size children according to parent
• Important: You must configure another layout if you want dynamic sizing of child items.

Column Layout
• Extends AutoLayout
• Manages Width of child items
• Allows wrapping of child items
• Does not size children vertically

Fit Layout
• Extends Container Layout
• Designed to size a single child item to the full size of a Container
• *does not allow scrolling

Anchor Layout
• Extends Container Layout
• Designed to dynamically size 1+ child items in both height and width dimensions based on rules
• known as anchor “anchor”
• does allow scrolling

Absolute Layout
• Extends Anchor Layout
• Designed to dynamically position 1+ child items in both X and Y coordinate space
• Does not dynamically size children
• does allow scrolling

Border Layout
• Extends Container Layout, automatically sizing children
• Organizes child items into “regions”
• north, south, east, west
• Regions can be resizable or collapsible
• Requires a center region

BoxLayouts
• Box is extends Container, and is a base class for HBox VBox
• HBox organizes children in a horizontal row (side by side)
• VBox organizes them in a vertical stack
• useful layout configs: align, pack
• child configs: height, width, flex

2014년 11월 26일 수요일

ExtJS Project - With C# - Chapter 1




Ext.onReady(function() {
    Ext.tip.QuickTipManager.init();
    Ext.state.Manager.setProvider(Ext.create('Ext.state.CookieProvider'));
    var viewport = Ext.create('Ext.Viewport', {
        layout: 'border',
        id: 'smartworksView',
        items: [cardPanelContent]
    });
    var menu = getQueryParam('menu');
    if (menu == null || menu == "") {
        menu = "AL";
    }
    changeContentView(menu);
});

function getQueryParam(name) {
    var regex = RegExp('[?&]' + name + '=([^&]*)');

    var scriptEls = document.getElementsByTagName('script'),
        path = scriptEls[scriptEls.length - 1].src,
        i = 3

    while (i--) {
        path = path.substring(0, path.lastIndexOf('/'));
    }
       
    var match = regex.exec(location.search) || regex.exec(path);
    return match && decodeURIComponent(match[1]);
}

var cardPanelContent = new Ext.Panel({
    xtype: 'panel',
    region: 'center',
    id: 'cardPanelContent',
    header: false,
    layout: 'card',
    activeItem: 0,
    items: [
                ImageMngView, userDocMainPanel, PrivateDocMainPanel
           ]
});