Sunday, October 2, 2011

Creating a contact book using Flex, AIR and SQLite database: Part 8

In this tutorial we will add a printing feature to our contact book application.

We are going to add 2 more buttons to our contact book's tool panel - Print selected and Print all. This will allow the user to be able to print all the items from his contact book, or select specific contacts and only print them.

The printing will be done by creating a temporary PrintDataGrid object, loading it with data, printing it, and then removing the temporary grid object.

In this tutorial we will only cover the functionality of the Print All button, but we will add both of them to the stage now anyway. You may also see that I made some changes to the tool panel in the application - specifically, I added blank form items to create blank spaces between certain form items.

<mx:Form>
<mx:FormItem label="First name" required="true"><s:TextInput id="t_fname"/></mx:FormItem>
<mx:FormItem label="Last name" required="true"><s:TextInput id="t_lname"/></mx:FormItem>
<mx:FormItem label="Phone"><s:TextInput id="t_phone" restrict="0-9 " /></mx:FormItem>
<mx:FormItem label="Email"><s:TextInput id="t_email"/></mx:FormItem>
<mx:FormItem>
<s:Button id="b_new" label="Create new item" click="createNew();" />
<s:Button id="b_clear" label="Clear fields" click="clearFields();" />
<s:Button id="b_save" label="Save changes" enabled="false" click="onSave();" />
<s:Button id="b_delete" label="Delete selected" enabled="false" click="onDelete();" />
</mx:FormItem>
<mx:FormItem/>
<mx:FormItem label="Search"><s:TextInput id="t_search"/></mx:FormItem>
<mx:FormItem>
<s:HGroup>
<s:Button id="b_search" label="Search" click="doSearch();" />
<s:Button id="b_showall" label="Show all" click="showAll();" />
</s:HGroup>
</mx:FormItem>
<mx:FormItem/>
<mx:FormItem label="Printing">
<s:Button label="Print selected" />
<s:Button label="Print all" click="printData();" />
</mx:FormItem>
</mx:Form>

As you can see, the Print all button calls a printData function.

Let's create that function.

private function printData():void{

}

Here we need to create a print job object and a print data grid object. Note, that we will be creating a FlexPrintJob instead of a PrintJob instance:

private function printData():void{
var pJob:FlexPrintJob = new FlexPrintJob();
var pGrid:PrintDataGrid = new PrintDataGrid();
}

We will need to create data grid columns for this grid separately, we can't use the existing AdvancedDataGridColumns, because they are for Advanced datagrids. This time, we just need regular DataGridColumn objects.

private function printData():void{
var pJob:FlexPrintJob = new FlexPrintJob();
var pGrid:PrintDataGrid = new PrintDataGrid();

var col1:DataGridColumn = new DataGridColumn();
col1.dataField = "fname";
col1.headerText = "First name";
var col2:DataGridColumn = new DataGridColumn();
col2.dataField = "lname";
col2.headerText = "Last name";
var col3:DataGridColumn = new DataGridColumn();
col3.dataField = "phone";
col3.headerText = "Phone";
var col4:DataGridColumn = new DataGridColumn();
col4.dataField = "email";
col4.headerText = "Email";

}

Now we call the start() method of the print job. It will also be located in a conditional check, to make sure that there already is something that is being printed. Inside the conditional, we will use the addElement method to add the new grid to the stage. We will set its width and height to pageWidth and pageHeight of the printJob, as well as set its columns and dataProvider. After that, we use the addObject() method of the print job to add the grid to the printing area, and then we use the send() method to finally start printing. After that, we remove the grid using removeElement().

private function printData():void{
var pJob:FlexPrintJob = new FlexPrintJob();
var pGrid:PrintDataGrid = new PrintDataGrid();

var col1:DataGridColumn = new DataGridColumn();
col1.dataField = "fname";
col1.headerText = "First name";
var col2:DataGridColumn = new DataGridColumn();
col2.dataField = "lname";
col2.headerText = "Last name";
var col3:DataGridColumn = new DataGridColumn();
col3.dataField = "phone";
col3.headerText = "Phone";
var col4:DataGridColumn = new DataGridColumn();
col4.dataField = "email";
col4.headerText = "Email";

if (pJob.start()) {
addElement(pGrid);

pGrid.width = pJob.pageWidth;
pGrid.height = pJob.pageHeight;

pGrid.dataProvider = contactList.dataProvider;
pGrid.columns = [col1, col2, col3, col4];

pJob.addObject(pGrid);

pJob.send();

removeElement(pGrid);
}
}

And here's the full code:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                       xmlns:s="library://ns.adobe.com/flex/spark"
                       xmlns:mx="library://ns.adobe.com/flex/mx" 
   width="660" height="440"
   creationComplete="init();"
   title="Flex contact book"
   >
   
<fx:Script>
<![CDATA[
import flash.data.SQLConnection;
import flash.events.SQLEvent;
import flash.data.SQLMode;
import flash.filesystem.File;
import flash.geom.Rectangle;
import flash.net.Responder;
import flash.data.SQLStatement;
import flash.printing.PrintJob;
import mx.collections.ArrayCollection;
import mx.collections.Sort;
import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
import mx.controls.Alert;
import flash.data.SQLResult;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.printing.FlexPrintJob;
import mx.printing.PrintDataGrid;
import mx.validators.Validator;
import mx.core.FlexGlobals;

private var connection:SQLConnection;
[Bindable]
private var listData:ArrayCollection;

private function init():void {

var dbFile:File = File.applicationStorageDirectory.resolvePath("database.db");
connection = new SQLConnection();
connection.addEventListener(SQLEvent.OPEN, onOpen);
connection.openAsync(dbFile, SQLMode.CREATE);
}

private function onOpen(evt:SQLEvent):void{
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "CREATE TABLE IF NOT EXISTS contacts (id INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT, lname TEXT, phone TEXT, email TEXT)";
stat.execute(-1, new Responder(selectItems));
}

private function selectItems(evt:SQLResult):void{
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "SELECT id, fname, lname, phone, email FROM contacts ORDER BY id";
stat.execute( -1, new Responder(onSelected));
b_save.enabled = false;
b_delete.enabled = false;
}

private function onSelected(evt:SQLResult):void {
var tempSort:Sort;
if (listData!=null) {
tempSort = listData.sort;
}
listData = new ArrayCollection(evt.data);
listData.sort = tempSort;
listData.refresh();
}

private function createNew():void {
if(fieldsCheck()){
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "INSERT INTO contacts (fname, lname, phone, email) VALUES (@fname, @lname, @phone, @email)";
stat.parameters["@fname"] = t_fname.text;
stat.parameters["@lname"] = t_lname.text;
stat.parameters["@phone"] = t_phone.text;
stat.parameters["@email"] = t_email.text;
stat.execute( -1, new Responder(selectItems));
}
}

private function onChange():void {
b_save.enabled = true;
b_delete.enabled = true;
t_fname.text = contactList.selectedItems[0].fname;
t_lname.text = contactList.selectedItems[0].lname;
t_phone.text = contactList.selectedItems[0].phone;
t_email.text = contactList.selectedItems[0].email;
if (contactList.selectedItems.length > 1) {
b_save.enabled = false;
}
}

private function onDelete():void {
for (var i:int = 0; i < contactList.selectedItems.length; i++){
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "DELETE FROM contacts WHERE id=" + contactList.selectedItems[i].id;
stat.execute( -1, new Responder(selectItems));
}
t_fname.text = t_lname.text = t_phone.text = t_email.text = "";
}

private function onSave():void {
if (fieldsCheck()) {
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "UPDATE contacts SET fname=@fname, lname=@lname, phone=@phone, email=@email WHERE id=" + contactList.selectedItems[0].id;
stat.parameters["@fname"] = t_fname.text;
stat.parameters["@lname"] = t_lname.text;
stat.parameters["@phone"] = t_phone.text;
stat.parameters["@email"] = t_email.text;
stat.execute( -1, new Responder(selectItems));
t_fname.text = t_lname.text = t_phone.text = t_email.text = "";
}
}

private function clearFields():void {
t_fname.text = t_lname.text = t_phone.text = t_email.text = "";
}

private function fieldsCheck():Boolean {
var validatorErrors:Array = Validator.validateAll(nameValidators);
if (validatorErrors.length > 0) {
Alert.show("You have to fill in first name, last name and at least 1 other contact field!", "Oops!");
return false;
}else if (valid_phone.validate(t_phone.text).type != "valid" && valid_email.validate(t_email.text).type != "valid") {
Alert.show("You have to fill in at least 1 contact field, other name first name and last name! (You need to have at least 3 fields filled in, including first name and last name.)", "Oops!");
return false;
}else{
return true;
}
}

private function doSearch():void{
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "SELECT id, fname, lname, phone, email FROM contacts WHERE fname LIKE @search OR lname LIKE @search OR phone LIKE @search OR email LIKE @search ORDER BY id;";
stat.parameters["@search"] = "%" + t_search.text + "%";
stat.execute( -1, new Responder(onSelected));
b_save.enabled = false;
b_delete.enabled = false;
}

private function showAll():void {
var stat:SQLStatement = new SQLStatement();
stat.sqlConnection = connection;
stat.text = "SELECT id, fname, lname, phone, email FROM contacts ORDER BY id";
stat.execute( -1, new Responder(onSelected));
b_save.enabled = false;
b_delete.enabled = false;
}

private function printData():void{
var pJob:FlexPrintJob = new FlexPrintJob();
var pGrid:PrintDataGrid = new PrintDataGrid();

var col1:DataGridColumn = new DataGridColumn();
col1.dataField = "fname";
col1.headerText = "First name";
var col2:DataGridColumn = new DataGridColumn();
col2.dataField = "lname";
col2.headerText = "Last name";
var col3:DataGridColumn = new DataGridColumn();
col3.dataField = "phone";
col3.headerText = "Phone";
var col4:DataGridColumn = new DataGridColumn();
col4.dataField = "email";
col4.headerText = "Email";

if (pJob.start()) {
addElement(pGrid);

pGrid.width = pJob.pageWidth;
pGrid.height = pJob.pageHeight;

pGrid.dataProvider = contactList.dataProvider;
pGrid.columns = [col1, col2, col3, col4];

pJob.addObject(pGrid);

pJob.send();

removeElement(pGrid);
}
}

]]>
</fx:Script>

<fx:Declarations>
<fx:Array id="nameValidators">
<mx:StringValidator source="{t_fname}" property="text" required="true" />
<mx:StringValidator source="{t_lname}" property="text" required="true" />
</fx:Array>
<mx:PhoneNumberValidator id="valid_phone" source="{t_phone}" property="text" required="true" />
<mx:EmailValidator id="valid_email" source="{t_email}" property="text" required="true" />
</fx:Declarations>
<s:HGroup width="500">
<mx:AdvancedDataGrid id="contactList" width="400" height="400" dataProvider="{listData}" change="onChange();" allowMultipleSelection="true">
<mx:columns>
<mx:AdvancedDataGridColumn dataField="fname" headerText="First name"/>
<mx:AdvancedDataGridColumn dataField="lname" headerText="Last name"/>
<mx:AdvancedDataGridColumn dataField="phone" headerText="Phone"/>
<mx:AdvancedDataGridColumn dataField="email" headerText="Email"/>
</mx:columns>
</mx:AdvancedDataGrid>
<s:VGroup horizontalAlign="center">
<mx:Form>
<mx:FormItem label="First name" required="true"><s:TextInput id="t_fname"/></mx:FormItem>
<mx:FormItem label="Last name" required="true"><s:TextInput id="t_lname"/></mx:FormItem>
<mx:FormItem label="Phone"><s:TextInput id="t_phone" restrict="0-9 " /></mx:FormItem>
<mx:FormItem label="Email"><s:TextInput id="t_email"/></mx:FormItem>
<mx:FormItem>
<s:Button id="b_new" label="Create new item" click="createNew();" />
<s:Button id="b_clear" label="Clear fields" click="clearFields();" />
<s:Button id="b_save" label="Save changes" enabled="false" click="onSave();" />
<s:Button id="b_delete" label="Delete selected" enabled="false" click="onDelete();" />
</mx:FormItem>
<mx:FormItem/>
<mx:FormItem label="Search"><s:TextInput id="t_search"/></mx:FormItem>
<mx:FormItem>
<s:HGroup>
<s:Button id="b_search" label="Search" click="doSearch();" />
<s:Button id="b_showall" label="Show all" click="showAll();" />
</s:HGroup>
</mx:FormItem>
<mx:FormItem/>
<mx:FormItem label="Printing">
<s:Button label="Print selected" />
<s:Button label="Print all" click="printData();" />
</mx:FormItem>
</mx:Form>
</s:VGroup>
</s:HGroup>

</s:WindowedApplication>

Next time we will work on the Print Selected feature.

Thanks for reading!

Related:

Creating a contact book using Flex, AIR and SQLite database: Part 1
Creating a contact book using Flex, AIR and SQLite database: Part 2
Creating a contact book using Flex, AIR and SQLite database: Part 3
Creating a contact book using Flex, AIR and SQLite database: Part 4
Creating a contact book using Flex, AIR and SQLite database: Part 5
Creating a contact book using Flex, AIR and SQLite database: Part 6
Creating a contact book using Flex, AIR and SQLite database: Part 7
Creating a contact book using Flex, AIR and SQLite database: Part 9
Creating a contact book using Flex, AIR and SQLite database: Part 10
Creating a contact book using Flex, AIR and SQLite database: Part 11
Creating a contact book using Flex, AIR and SQLite database: Part 12
Creating a contact book using Flex, AIR and SQLite database: Part 13
Creating a contact book using Flex, AIR and SQLite database: Part 14
Creating a contact book using Flex, AIR and SQLite database: Part 15
Creating a contact book using Flex, AIR and SQLite database: Part 16

No comments:

Post a Comment