the singularity of being and nothingness
Posts tagged ExtJS 4
ExtJS 4: Custom Editor for Property Grid
Dec 30th
Yesterday, I was helping someone figure out how to add a custom, complex editor for use in a ExtJS Property Grid.
The Anatomy of a Property GridFor some context, a Property Grid is like an editable grid, but instead of editing rows of data, you use a grid like interface to edit the properties of a single object. Think of it like the interface you’d use when defining database properties in SSMS…
By default, the Property Grid has several editors for simple types like strings, dates, booleans and numbers. Better yet, ExtJS will automatically try to detect the correct type, and specify the appropriate editor for you.
Out of the Box is Never EnoughBut of course, out of the box never gets you 100% of the way. Imagine that we have a cluster of properties, one property of which is a complex data type. Consider this example:
source: { name: "My Object", created: Ext.Date.parse('10/15/2006', 'm/d/Y'), timeofday: "12:00 PM", available: false, version: 0.01, description: Ext.encode({ product: 'Clorox', tagline: 'The Shinyest White!' }) }
As you can see, most of the properties are very simple. However, the last one (description) is complex: in this example, it’s a serialized object. If we 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 >
Virtual Directory-Driven ExtJS 4 Development
Nov 15th
Over the last several months, I’ve been incredibly lucky to be able to work with ExtJS 4 on a daily basis. And I’m not just talking about dabbling here and there; rather, I mean developing a full-on legit application. It’s been awesome.
As I’ve been building this application, I’ve developed a TON of custom, reusable code. Some of it is app-specific, but a lot of it is application-agnostic. For example, in my ColdFusion settings, all AJAX responses are prepended with “//”. Doesn’t sound like a big deal, but the default ExtJS 4 data readers don’t understand this…so I built a set of custom reader extensions that solve this problem.
So now that the application is more in “maintenance” mode, I’ve been taking an inventory of all the custom, globally-reusable extensions and plugins that I’ve created. And it’s got me wondering about how, exactly, one should (or could) leverage all this reusable goodness in a way that doesn’t require a clunky copy-paste for every project.
WorkspacesWith the release of Sencha Cmd 3.0, you can now leverage the concept of a “workspace” to aid in managing reusable code. I’ve not personally used this yet, but it seems like a really nice solution.
There is one serious More >
ExtJS 4: Filtering on Multiple Fields
Nov 23rd
Filtering ExtJS data stores is stupid-simple. When filtering, you have 2 main options:
- Filtering on a property (e.g., “field”)
- Filtering with a custom function
Ext.define('Person', { extend: 'Ext.data.Model', idProperty: 'id', fields: [ {'firstname', type:'string'}, {'middlename', type: 'string'}, {'lastname', type: 'string'} ] });
Ext.create('Ext.data.Store', { autoLoad: true, model: 'Person', storeId: 'PersonStore', proxy: { type: 'ajax', url: 'myurl.json', reader: { type: 'json', root: 'people' } } });Ok, now that we have those set up, let’s say that we want to filter our results to only those people whose last name contains “son” (like “Watson”). Using the property filter, we can do this very simply:
var store = Ext.data.StoreManager.lookup('PersonStore'); var peoplefilter = new Ext.util.Filter({ property: 'lastname', value: 'son', anyMatch: true, caseSensitive: false, root: 'data' }); store.filter(peoplefilter);
Nothing to it, right? There are two important parts here. First, for “property”, we are simply specifying the field in our Model which we want to filter on…in this case, “lastname.” Second, we specify that we want the filter to look at the “data” object of each record–otherwise, it will fail miserably 🙂
For simple filtering, using the “property” method will get you by pretty good. For More >
ExtJS 4 Theming: Custom UIs
Sep 29th
In a previous post, I walked through the simple process of creating a custom UI for a toolbar in Sencha Touch. Since theming in Sencha Touch and ExtJS 4 are extremely similar, I thought I’d walk through the same process, but with an ExtJS 4 flair.
In fact, the last post that I wrote was meant to be this one. However, as I worked through the process of creating a custom UI, I found that the setup of Compass compilation for ExtJS 4 might have some *gotchas* that could trip people up (like me), so I decided to start from the beginning, get a solid foundation, and now move on to the actual fun stuff.
Ok? Good? On we go!
What We’re Going to MakeIn this walkthrough, we’re going to try to accomplish a few things.
Objective #1: I want to show how it’s perfectly possible (maybe preferable?) to mix custom UIs with the stylesheets/images/etc. of the “default” ExtJS 4 theme. In this particular example, we’re going to create a custom Ext.ProgressBar UI.
Objective #2: We’re also going to create a custom stylesheet that produces only the minimum of what we need for the “application” we’re going to build. So instead of having a monster ext-all.css file More >
ExtJS 4 Theming: Getting This Thing to Go
Sep 28th
Recently, I’ve been concentrating a lot on theming for Sencha Touch. If you’ve read much of what I’ve posted, you know that I really love how the framework is put together, and think the SASS-y mode of custom theming is just awesome.
Of course, ExtJS 4 has many of the same theming features, and a very similar workflow for creating and compiling custom themes. I’ve been playing around within some theming experiments, and learned some frustrating lessons along the way. So I thought I’d share, step-by-step, how I set up my environment for successfully compiling custom stylesheets for ExtJS 4…just in case you’re having issues 🙂
Getting StartedFirst off, I’m assuming you already have Ruby and the Compass/SASS gem installed. If you don’t take a few minutes to get that done. For instructions on how to do this, check out this walkthrough.
Before breezing on, take a few deep breaths. This is a critical step…if you don’t do it right, you have hours of frustration ahead of you.
I start off with a blank project (I’m using Eclipse, so insert whatever terminology you use for your IDE). First, I create the root folder for my project. I’m calling this one “playground.”
With my root 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: ComponentQuery Selectors in a Controller
Aug 6th
In ExtJS 4, you can do some pretty powerful stuff inside your controllers using ComponentQuery. In the following example, I have a simple grid panel view, and I’m using ComponentQuery in my controller to handle itemcontextmenu events within the grid:
views/Bookmarks.jsExt.define("ME.view.bookmarks.List", { extend: "Ext.grid.Panel", alias: "widget.bookmarks", store: "Bookmarks", scroll: "vertical", title: "My Bookmarks", initComponent: function() { this.columns = [ { text: "Bookmark", dataIndex: "title", flex: 1, renderer: function(value,meta) { meta.tdAttr = 'data-qtip="' + value + '"'; return value; } }, { text: "Created", dataIndex: "created", xtype: "datecolumn", format: "m-d-y", hidden: true } ]; this.callParent(arguments); } });controllers/Bookmarks.js
Ext.define("ME.controller.Bookmarks", { extend: "Ext.app.Controller", stores: ["Bookmarks"], models: ["Bookmark"], views: ["bookmarks.List"], init: function() { this.control({ "bookmarks": { 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 Forever", icon: "images/delete.png", handler:function(btn) { me.deletebookmark(record,item); } } ], defaultAlign: "tl" }); } item.ctxMenu.showBy(item); } } }); } });
First things first. You’ll notice this bit in the view:
alias: "widget.bookmarks"
This allows me to define my class as a custom xtype. This is important because you can use ComponentQuery to select components by xtype. With this in mind, I can now use the alias of my More >
ExtJS 4: A Textfield, a Grid, and Some Keystroke Interception
Aug 2nd
Recently, I’ve been working pretty furiously on the rewrite of Gloss, my first serious ExtJS application. I wrote Gloss in ExtJS 3, but wanted to give it a much-needed overhaul now that ExtJS 4 is out.
One of the more useful features of Gloss (well, I think it is at least) is the search functionality. In my rework, I’ve been trying to solidify some of the keyboard navigation to allow for a more fluid experience.
Ideally, I want the flow to go something like this:
- Enter a search, with as-you-type results
- When the full list of results is returned, be able to TAB from search text field to first row in the list of results
- Be able to TAB or DOWN ARROW to the next result in the list
- When focused on the desired result, be able to strike ENTER or SPACE to load the record
I’ll start with the last two: navigating inside the grid panel itself.
Grid NavigationWith ExtJS 4, this is stupid easy. In my Search controller, I have some listeners set up. They’re keyed in on the “itemkeydown” event of the grid.
Ext.define("Gloss.controller.Search", { extend: "Ext.app.Controller", init: function() { this.control({ "searchgrid *": { itemkeydown: function(grid,rec,item,idx,e,opts) { if(e.keyCode==13 || e.keyCode==32) { ... do some stuff More >
ExtJS Quickie: Full Width Text Fields
Jul 17th
Ok, so a lot of posts I make are not so much about “hey, look at this cool thing I figured out” as much as it is saving a reminder of myself for how to do something when I inevitably forget it later on 🙂
So for today’s example, the problem I was having was how to make a textfield fill up 100% width of a panel. I think in earlier versions of ExtJS, there was an “autoWidth” option, but alas, it doesn’t work in ExtJS 4. Moreover, using “width: ‘100%'” doesn’t work either, since the width option expects a numeric value.
Turns out, this is pretty stupid and simple. Here’s a quick example:
Ext.define("Gloss.view.search.Form", { extend: "Ext.form.Panel", alias: "widget.searchform", frame: true, items: [ { xtype: "textfield", anchor: "100%" } ], initComponent: function() { this.callParent(arguments); } });
As you can see, adding in the “anchor: 100%” solves the issue quite nicely. Now, as the container is resized, the textfield will resize as well.
Share this: