Ext JS 4 – Plugin to Add Icons to a Panel Header

May 22, 2012 Leave a comment

Recently in my app I had multiple grid panels that needed icons added to the header, where the title goes. Instead of duplicating the code in multiple places, I created a simple plugin that I could use on any panel anywhere in my application.

Here is the code of the plugin. It’s really simple, but helps keep my grid/panel code cleaner.

And example usage of a grid config with the plugin:

{
	xtype: 'grid',
	title: 'My Grid Title',
	columns : [
	],
	plugins: [{
		ptype: "headericons",
		headerButtons : [
			{
				xtype: 'button',
				iconCls: 'icon-page-white-excel',
				scope: this,
				handler: this.onExportToExcel
			}
		]
	}]
}

And here is a screenshot, that shows two different panel headers that I have. One with one icon and one with two.
Screenshot of Icons added to Panel Header

Version Info: Ext JS 4.1

Categories: ExtJS Tags: , , ,

Ext JS 4: “Link” from One Tab to Another

April 13, 2012 Leave a comment

I have a pretty typical Ext JS app.  Tab panels and within each tab border layouts with multiple grids.  One thing the app does is manage users and one tab shows user details.  Anywhere else in the app that shows a user name, I want to link that user name to the user detail (not in a dialog, but actually switch to the user detail tab).  Typically, the user names are listed in grids.  Here is what I did to hook up the “links” to the tab.

I started out using an <a> tag, but settled on a <button> tag to avoid the hash being added to the url and messing up my history.

Here is the renderer function for when the links are in a grid.  It’s pretty straightforward, just renders the cell with button tag.


userNameLink : function(val) {
    return Ext.String.format('<button type="button" class="userNameLink">{0}</button>', val);
}

Now style the link.  My css skills leave a lot to be desired.  I found this very helpful post which I used for the styling: Styling button elements to look like links


button.userNameLink {
     overflow:visible; 
     margin:0;
     padding:0;
     border:0;
     color: #2B547D;
     background:transparent;
     font:inherit;
     line-height:normal; 
     text-decoration:underline; 
     cursor:pointer; 
     -moz-user-select:text; 
}

button.userNameLink::-moz-focus-inner {
     padding:0;
     border:0;
}

Finally, now to do something with those “links”.  Right now they look good, but they aren’t doing anything!


Ext.getBody().on('click', this.handleUserNameLink,
    this, {
        delegate: 'button.userNameLink'
    });

The “handleUserNameLink” function does the heavy lifting of actually switching tabs and defaulting data, but this nifty code adds the handler to every single one of my links w/o me having to add it myself everywhere.

Helpful links:

Version info: Ext JS 4.0.7
Tested on IE6, IE8, Firefox 11, Chrome 18

Categories: ExtJS Tags: , ,

Create a SQLite database during an ant build

April 11, 2012 Leave a comment

I have a SQLite database that is used by my application.  It is not the main database but provides some supporting data for the application.  Every time I deploy my application to my local tomcat installation using ant, I want to recreate this database, using a sql script.  I do this by executing a sqlite .read command as one step in my build.

  1. Install sqlite and ensure it is in your path.
  2. Update my Eclipse Ant installation to include the Ant Contrib jars.
    1. I unpacked the jars to my eclipse/plugins/org.apache.ant.XXX/lib directory.
    2. In Eclipse->Window->Preferences->Ant, go to the Runtime section and add the ant-contrib.jar to the classpath.
  3. Within my ant build file I did the following:


<project name="myproject" basedir="." default="clean-deploy">

<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>

   <property file="build.properties"/>
   <property environment="env"/>

   <!-- assumes you have sqlite3 installed on the local machine and in the path -->
   <target name="createsqlitedb" description="build sqlite db">
      <propertyregex property="loc" input="${env.CATALINA_HOME}" regexp="\\" replace="\\\\\\\\\\\\\\\\" />
      <property name="myapp.web.dir" value="${loc}/webapps/${property.projectname}"/>
      <property name="tomcat.conf.dir" value="${loc}/conf"/>

      <echo message="src file for sqlitedb: ${myapp.web.dir}${property.sqlitedb.src}"/>
      <echo message="dest db for sqlitedb: ${tomcat.conf.dir}${property.sqlitedb.dest}" />
      <exec executable = "sqlite3">
          <arg value="${tomcat.conf.dir}${property.sqlitedb.dest}" />
          <arg value=".read ${myapp.web.dir}${property.sqlitedb.src}"/>
      </exec>
   </target>

</project>

The build.properties file has the properties in it such as property.sqlitedb.src and property.sqlitedb.dest.  The file itself has standard sqlite sql statements in it.

Helpful links:

Categories: Eclipse Tags: , ,

Spring 3 @Autowired Unit Tests with Mockito

March 2, 2012 Leave a comment

I’ve been wanting to enhance the unit tests I have in my application for awhile. I’m using Spring 3 testing facilities, but most of my tests are “integration” tests. I finally carved out a bit of time to enable better unit tests in my application. This is an example of a unit test of a simple service class using Spring 3 annotations. I am using Mockito to mock the dependencies.

First my service class. Like I said, simple. Just two methods and straightforward logic.

package my.app.service;

import java.util.List;

import my.app.dao.SupervisorDAO;
import my.app.model.Supervisor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SupervisorService {

	@Autowired private SupervisorDAO supervisorDao;

	@Transactional(readOnly=true)
	public List getSupervisors() {
		return supervisorDao.getSupervisors();
	}

	/**
	 * Determine if the supervisor is responsible for any users for the
	 * specified department
	 * @param dbId The dbId of the supervisor
	 * @param department The department to look for
	 * @return true if there are users assigned to the superivsor for the department
	 */
	public boolean isSupervisorResponsibleForUser(int dbId, String department) {
		if (dbId == 0) {
			throw new IllegalArgumentException("A dbId is required");
		}
		if (department == null) {
			throw new IllegalArgumentException("department is required");
		}
		boolean hasUsers = false;
		int numAssignedUsers = supervisorDao.getUserCountForSupervisor(dbId, department);
		if (numAssignedUsers > 0) {
			hasUsers = true;
		}
		return hasUsers;
	}
}

The unit test. I need to mock the dao object to create a repeatable unit test of the service class. Here’s the code:

package my.app.service;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

import my.app.dao.SupervisorDAO;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SupervisorServiceUnitTest {

	@Mock private SupervisorDAO mockSupervisorDao;
	@InjectMocks private SupervisorService supervisorService;

	@Before
	public void init() {
		when(mockSupervisorDao.getUserCountForSupervisor(1, "Department1"))
			.thenReturn(2);
		when(mockSupervisorDao.getUserCountForSupervisor(1, "Department2"))
			.thenReturn(0);
	}

	@Test
	public void testIsSupervisorResponsibleForUserTrue() {
		boolean isSupervisor = supervisorService.isSupervisorResponsibleForUser(1, "Department1");
		assertTrue(isSupervisor);
	}

	@Test
	public void testIsSupervisorResponsibleForUserFalse() {
		boolean isSupervisor = supervisorService.isSupervisorResponsibleForUser(1, "Department2");
		assertFalse(isSupervisor);
	}

	@Test(expected=IllegalArgumentException.class)
	public void testIsSupervisorResponsibleRequiredDbId() {
		supervisorService.isSupervisorResponsibleForUser(0, "Department3");
	}

	@Test(expected=IllegalArgumentException.class)
	public void testIsSupervisorResponsibleRequiredDivision() {
		supervisorService.isSupervisorResponsibleForUser(1, null);
	}
}

The key things that I learned along the way:

  • Use @RunWith(MockitoJUnitRunner.class) to run this test
  • Use the @Mock annotation for the classes that need to be mocked within the class you are testing. Use the @InjectMocks annotation on the class you are testing. The @Mock classes are injected into the @InjectMocks class. I guess this should have been obvious, but it wasn’t to me.

It’s a simple class and a simple unit test, but it’s a start. It gets me over the hump of having the correct jars and knowing how to get a test up and running. I am new to the behavior driven style of Mockito, but this works well for me in this unit test. I think it is clean and easy to read.

Some links that were helpful to me (disclaimer, some of these are for older versions of Mockito)

Version Info:

  • Spring 3.0.5
  • Mockito 1.9.0
Categories: spring3 Tags: , ,

Ext JS 4 – Cell Editing and Blur Event

March 2, 2012 Leave a comment

I have a grid panel using the cell editing plugin. There is also a Save button on panel top toolbar. When editing a field in the grid and then clicking the save button without tabbing out of the field being edited the blur event of the cell occurred after the Save button handler. It happened consistently in IE8.

I found this very helpful post EditorGridPanel -delay in firing Blur Event causes Bug on the Sencha forums and utilized the same solution, with a slight update for Ext 4. I called plugin.completeEdit() at the beginning of my save handler.

Plugin declaration:

var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', {
	pluginId: 'cellplugin',
	clicksToEdit: 1,
	listeners : {
		scope: this,
		// put listeners here
	}
});

At the beginning of the save button handler:

onSave : function () {
	var grid = this.child('#divGrid'), plugin;

	plugin = grid.getPlugin('cellplugin');
	plugin.completeEdit();
	
	// now do what is needed for save
}

Ext JS Version: 4.0.7

Categories: ExtJS Tags: , , ,

Ext JS 4: When you want the message box to stop processing

February 16, 2012 6 comments

As you know, the Ext JS message box does not stop the flow in your app. Here is a pattern that can be used to stop or continue the flow as needed. My example is on a listener for a grid beforeselect event.

myEventHandler : function (rowModel, rec) {
	if (this.canContinue) {
		this.canContinue = false;
		return true;
	} else {
		if (this.down('#myForm').getForm().isDirty()) {
			Ext.Msg.confirm("Save Changes?",
				"There are unsaved changes.  Save them?",
				function(buttonId) {
					if (buttonId === 'no') {
						// User wants to discard changes and continue.
						// Set the flag to true and then call the action
						// a second time.  This time the action will go thru.
						this.canContinue = true;
						rowModel.select(rec);
					} else {
						this.canContinue = false;
					}
				},
				this
			);
			return false;
		}
		return true;
	}
}

This pattern is from Condor and is posted in this forum thread: MessageBox.confirm doesnt stop in some cases

Categories: ExtJS Tags: , ,

Ext JS 4: Poor Man’s Input Field Dynamic Help

February 15, 2012 Leave a comment

I wanted to put a dynamic tool tip on some input fields in a form in my application. I wanted to use Ext JS Quicktip, but it wasn’t quite what I wanted, because I wanted the tip to show on focus, not mouse hover. I created a very simple one in Ext JS 4.0.7, by doing the following.

1. After render of my panel I added the following code to define the tip. It is just a basic tip


Ext.define('My.Panel', {
	extend: 'Ext.panel.Panel',
	
	// All your configs, initializations, etc.

	afterRender : function () {
		this.callParent(arguments);
		this.fieldHelp = Ext.create('Ext.tip.Tip', {
			shadow: false
		});
	}
});

2. For the input fields where I want the tooltip to show, I added a fieldHelp config and listeners for the focus and blur events.

{
	name: 'myField',
	fieldLabel: 'Name',
	// Usual configs here
	fieldHelp: 'Help text specific to this field',
	listeners: {
		scope: this,
		focus: this.onFieldFocus,
		blur: this.onFieldBlur
	}
}

3. Last, the onFieldFocus and onFieldBlur handlers:

onFieldFocus : function (el) {
	var text = el.fieldHelp,
		xy;
	if (typeof text !== "undefined") {
		xy = el.getEl().getAnchorXY('r');
		xy[0] += 5;
		xy[1] -= 4;
		this.fieldHelp.update(text);
		this.fieldHelp.fieldId = el.id;
		this.fieldHelp.showAt(xy);
	}
},

onFieldBlur : function (el) {
	if (this.fieldHelp.isVisible() && this.fieldHelp.fieldId === el.id) {
		this.fieldHelp.hide();
	}
},

And there you have it, simple, dynamic help that appears to the right of a field when the field has focus.

Categories: ExtJS Tags: , ,
Follow

Get every new post delivered to your Inbox.