the singularity of being and nothingness
Posts tagged Sencha
Getting Started with Ext JS 5
Aug 8th
It has been a while since I’ve blogged, and during my absence, Sencha went and released Ext JS 5. If you haven’t already, check out all the new features of both 5.0.0 and 5.0.1. I will admit that I am extremely excited to start using it…especially the MVVM architecture. I’m impressed that Sencha keeps evolving their framework, even so soon after such a radical change to MVC in Ext JS 4. While such adjustments might create frustrations for others, I see it as a good sign that the framework is on a good path and has momentum for the future.
So enough with the free promotional copy. Since I am, like many, just starting to get my feet wet with all the changes in Ext JS 5, I thought it might be interesting to do a series of short articles about some of new features. Over the next few weeks, I hope to cover a number of topics, including (but not limited to):
- Routing (hooray!)
- Data binding
- View models and controllers
- Chained stores
- Grid widgets
- Breadcrumbs
- more…!
Let’s get started, shall we?
A New Version, A New AppThere is, of course, a migration guide for upgrading your 4.x app to Ext JS 5. But that’s lame. We want to start with something More >
Ext JS 4: Demystifying Grid Paging
Jan 25th
Between the Ext JS forums and Stack Overflow, there are LOTS of questions that get asked about grids, and for obvious reasons: the data grid is one of Ext JS’s most powerful data-driven components.
With new developers especially, I see a common question asked quite a bit about a pretty standard bit of functionality: the “paged” data set. In this post, I’m not going to necessarily go into all the nuances of *how* to configure a paged grid in Ext JS (there are plenty of docs for that). Rather, I want to focus on *what* paging in an Ext JS grid is, and how it relates to the server.
What It Isn’tThe most important rule to understand when dealing with paging data from a remote data set is that Ext JS grids–regardless of how powerful they are–are STUPID. By this, I don’t mean that they are poorly built, or that they lack features, don’t work, or anything like that. Rather, I simply mean that when it comes to the data you are asking them to display, they are completely ignorant. When you configure an Ext JS data grid to display (and page) remote data, you will be lost if you think that More >
ExtJS Quickie: Custom Event Domain
May 25th
With ExtJS 4.2 came the awesome concept of Event Domains. Basically, these allow you to let your Controllers know about ALOT more events within your applications. For example, in 4.1, you could use the control() method within your controller to listen to component-level events. However, with Event Domains, you can now listen to events in the following domains: Global, Controller, Component, Store.
This is awesome, but there are other domains that you might want to tap. No fear, the Event Domain is easily extensible to include others!
A Proxy DomainIn my applications, I generally have a single proxy that handles all my stores’ AJAX traffic. A common event listener for the proxy is the exception event, which fires in the case of a server error response. In the past, I’ve generally just added this to the listener config of the proxy itself, and went about my business.
The problem, of course, is that you generally want to DO something when an exception occurs, such as displaying an error message, resetting the state of a store, etc. The problem with defining the listener directly on the proxy is that you have to intrude your application upon the proxy to communicate the exception beyond the proxy.
But with a custom Event More >
Virtual Directory-Driven ExtJS 4 Development – The Finale
Nov 24th
If you’ve been following along the last few posts, you’ve seen how it’s relatively simple to set up your local development environment to leverage global library assets to create ExtJS 4 applications. What you’ve probably also noticed is that there are a number of configurations (some one-time, others per-application) that need to be implemented before it will work. While these are not necessarily that big of a deal (especially in light of the benefits you gain), it’s still a lot. Here’s the full list:
- Generate application with Sencha Cmd
- Add virtual directories (ExtJS library, global plugins, and resources)
- Update ext.dir in /app/.sencha/workspace/sencha.cfg
- Add workspace.classpath in /app/.sencha/workspace/sencha.cfg
- Add full host path to /app/resources/theme/{themename}/theme.html
- Update $ext_path in /app/resources/sass/{themename}/config.rb
- Add fixes to /extroot/resources/themes/lib/Utils.rb (one time)
- Update /app/.sencha/app/build.impl.xml to copy theme images to app folder
- Develop application
- Build application and theme
So only 9 per-app steps…not too bad. But wouldn’t it be WAY better if this number could drastically reduced?
WARNING!! WARNING!! WARNING!!
What follows is a total hack. The steps outlined will show you how to modify your Sencha Cmd installation so that the configurations previously outlined will now be the “default”. These changes apply only to ExtJS 4 app creation and compile/build. I didn’t bother with the more advanced commands in Sencha Cmd, nor with anything relating More >
ExtJS 4: Applying Model Validations to Forms
Apr 23rd
One of my absolute favorite things about ExtJS’ data model is how simple it is to apply a Model instance to a form. If you’ve never done this before, consider the following data model:
Ext.define('Validations.model.Person', { extend: 'Ext.data.Model', fields: [ {name:"name", type:'string'}, {name:"age", type:"int"}, {name:"hobby", type:"string"} ] })
Also, assume we have a form defined like so:
Ext.define('Validations.view.people.Form', { extend: 'Ext.form.Panel', alias: 'widget.peopleform', bodyPadding: 10, border: false, initComponent: function() { var me = this; Ext.applyIf(me, { defaults: { width: 250, labelWidth: 70 }, items: [ { xtype: 'textfield', name: 'name', fieldLabel: 'Name' }, { xtype: 'numberfield', name: 'age', fieldLabel: 'Age', value: 20 }, { xtype: 'textfield', name: 'hobby', fieldLabel: 'Hobby' } ] }); me.callParent(arguments); } })
NOTE: Notice that the “name” properties of each form field maps 1:1 with the “name” properties in my Model.
Now, let’s say that we want to edit a Model instance. We could, of course, manually set the value of each form field to that of the corresponding field in the Model. However, this is clunky and unnecessary, given that the form itself has a method for doing this automatically. Consider the following:
// get More >
Quick Thoughts on Sencha Architect 2
Apr 21st
A few days ago, Sencha rolled out Sencha Architect 2, the major overhaul and rebranding of what was formerly Sencha Designer. You can check out the release blog post to get the low-down on all the new features.
When I saw the news about the release, I have to say I was a bit hesitant to look much further. I’ve tried Sencha Designer several times in the past, and I’ve been somewhat disappointed with it. Sure, it was great for laying out apps, but when you actually needed to *code*, it was lackluster at best. But even worse, I found it to be very buggy; it would crash at random times, and overall I found the process of trying to mockup an app to be more frustrating than anything else.
So initially, I wasn’t planning on even trying out the newest iteration. But then I noticed that one of the biggest additions to the product is support for creating a full ExtJS or Touch app–not just the UI. I felt I had to take a closer look, and I’m glad I did.
UIOut of the box, Architect 2 is worlds better than its previous iterations. The interface is slick and responsive, and the way More >
ExtJS 4: A Modified Ext.util.History
Aug 21st
I recently implemented Ext.util.History for the first time in a project that I’m working on. If you’re not familiar with History, it allows you to “register arbitrary tokens that signify application history state on navigation actions”. You can then take these “tokens” and use them in your application to display certain views, fire actions, etc. when the user uses their browser’s “back” and “forward” buttons. In other words, it can help you prevent your 1-page AJAX application from reloading completely when someone accidentally hits the back button. But on a more positive note, it allows your AJAX application to use regular navigation conventions of the browser to control in-application functionality. Pretty cool.
The best part about History, however, is that it is stupid-simple to implement. There are basically 3 steps:
- Initialize Ext.util.History
- Build in the “token-building” logic into your application at appropriate places
- Define the listener for handling History events.
That’s it. History is not only easy to implement, but it is also pretty unobtrusive–you can implement it fairly simply into an existing app without completely reworking the whole thing. There’s a lot more to History, of course, so be sure to check out the docs and Sencha’s example.
First, My Example…Before I talk about the More >
ExtJS 4: Intercepting a Window Closure
Aug 18th
In a blog post I ran across recently, someone was trying to intercept the closure of a window via the “X” icon in the top right corner. The idea was to be able to run additional processing before closing the window (such as confirming save/cancel of data, resetting a form, updating a record, or whatever else).
Turns out this is pretty simple to accomplish, but it’s good to understand what’s going on behind the scenes before implementing the solution.
The “Close” ToolWhen you specify that your Window (a glorified extension of Panel) is “closable” (the default behavior, btw), here’s what happens in the background:
initTools: function() { var me = this; me.tools = me.tools || []; ...... // Add subclass-specific tools. me.addTools(); // Make Panel closable. if (me.closable) { me.addClsWithUI('closable'); me.addTool({ type: 'close', handler: Ext.Function.bind(me.close, this, []) }); } // Append collapse tool if needed. if (me.collapseTool && !me.collapseFirst) { me.tools.push(me.collapseTool); } }
As you can see, if the Window is closable, a tool of “close” type is added automatically, and fires the panel’s “close” method when clicked. Here’s what close() looks like:
close: function() { if (this.fireEvent('beforeclose', this) !== false) { this.doClose(); } }
The important thing to note here is that the “beforeclose” More >
ExtJS 4: Adding an App-wide Keystroke Mapping
Aug 16th
In a previous post, I showed how it’s pretty simply to catch keystrokes in your controller, and then do cool stuff in your app. But what if you want to add an app-wide keystroke mapping? For example, consider you’re create something like Sencha’s desktop demo. Within such an interface, it might be nice to map keystrokes to functionality within your app (like initiating a search, closing a window, etc.).
So here’s an easy way to do that.
In this example, I’m creating an app-wide keystroke mapping for search functionality. When a user enters the keystroke of the letter “S” and the Ctrl key, I want to give focus to a search box that exists within the app.
First of all, here’s the app.js for my application:
Ext.application({ name: "MyApp", appFolder: "app", autoCreateViewport:true, controllers: ["Search"....], launch: function() { var map = new Ext.util.KeyMap(Ext.getBody(), { key: 83, ctrl: true, handler: function() { this.getController("Search").activatesearch(); }, More >
ItemClick and ItemContextMenu
Jul 8th
Custom context menus are one of the features of ExtJS that I love. They are stupid simple to add in, and ridiculously customizable–they can really add some value to your app and help preserve real estate if you have a lot of embedded actions that need to happen.
For example, in one of my controllers, I’m looking for the “itemcontextmenu” event on a grid:
this.control({ "bookmarks": { itemclick: function(...) { .... }, itemcontextmenu: function(view,record,item,index,e) { var me = this; var r = record.data; e.stopEvent(); if(item.ctxMenu) { item.ctxMenu = new Ext.menu.Menu({ items: [ { text: "Delete This Thing", icon: "images/delete.png", handler: function(btn) { me.deletebookmark(record,item); } } ] }); } } })
One of the issues I was running into, however, was that whenever I would “right” click using my Mac’s “magic mouse” (e.g., Ctrl+click), both the itemclick AND itemcontextmenu events would fire.
To debug this, I took a quick peek at the “event” object passed on both methods. This object provides a bunch of information about the event that was fired, including:
- any keys that triggered the event
- whether Ctrl was pressed
- whether Shift was pressed
- what “type” of event (e.g., “click” for a mouse event)
Armed with this information, I was able to adjust my “itemclick” listener a bit, More >