Archives of February 2009

Data communication between a pop-up created with PopUpManager class and its parent can be achieved with the following strategies in Flex:

1. Using bindable variables with BindingUtils

Origin:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import mx.binding.utils.BindingUtils;
			import mx.managers.PopUpManager;
			import mx.controls.Alert;
			public var popUp:MyPopUp_comp;
			[Bindable]
			public var myMainVar:String="Main Value";
			public function crearPopUp():void {
				popUp = MyPopUp_comp(PopUpManager.createPopUp(this, MyPopUp_comp, true));
				PopUpManager.centerPopUp(popUp);
				popUp.myPopUpVar=myMainVar;
                BindingUtils.bindProperty(this, "myMainVar", popUp, "myPopUpVar");
			}
		]]>
	</mx:Script>
	<mx:HBox>
		<mx:Button label="Create PopUp" click="crearPopUp()"/>
		<mx:Text text="myMainVar: {myMainVar}"/>
	</mx:HBox>
</mx:Application>

Pop-up:

<?xml version="1.0" encoding="utf-8"?>
<mx:Panel title="Mi PopUP" xmlns:mx="http://www.adobe.com/2006/mxml">
	<mx:Script>
		<![CDATA[
			[Bindable]
			public var myPopUpVar:String;
		]]>
	</mx:Script>
    <mx:TextInput text="{myPopUpVar}" change="myPopUpVar=event.target.text"/>
    <mx:Button id="close" label="Close"/>
</mx:Panel>

2. Using events to data actualization. Like other but you invoke functions in origin with the necessary parameters.

Origin:

[...]
popUp = MyPopUp_comp(PopUpManager.createPopUp(this, MyPopUp_comp, true));
PopUpManager.centerPopUp(popUp);
popUp.addEventListener("myEvent", handleMyEvent);
popUp["cancel"].addEventListener("click", handleCancel);
popUp["ok"].addEventListener("click", handleOK);
[...]

Pop-up:

[...]
<mx:Metadata>
	[Event("myEvent")]
</mx:Metadata>
[...]
<mx:Button id="ok" label="OK"/>
<mx:Button id="cancel" label="Cancel"/>
<mx:Button label="myEvent" click="dispatchEvent(new Event('myEvent'));"/>
[...]

3. Using a global model (Singleton) that it’s update from the pop-up.

There is a problem trying to upload files with multipart/form-data forms and attached them another variables. In a normal upload java system data will be corrupt.

There are several libraries to solve this problem:
- Apache: http://commons.apache.org/fileupload/
- O’Reilly: http://www.servlets.com/cos/index.html

Simple example using Apache library (commons-fileupload-1.2.1 y commons-io-1.4) to process files and variables sent through a POST form with enctype=multipart/form-data:

upload.html

<html>
<body>
	<form action="upload" method="post" enctype="multipart/form-data">
		<input type="file" name="fileName"/>
		<input type="hidden" name="Author" value="Arcadio Carballares"/>
		<input type="submit" value="Submit"/>
	</form>
</body>
</html>

UploadServlet.java

package com.arcadiocarballares;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class UploadServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
		doPost(req, res);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		proccessRequest(req, res);
		System.out.println ("Success!");
	}

	@SuppressWarnings("unchecked")
	protected void proccessRequest (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {

			if (ServletFileUpload.isMultipartContent(request)){
				ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
				List fileItemsList = servletFileUpload.parseRequest(request);

				Iterator it = fileItemsList.iterator();
				while (it.hasNext()){
					FileItem fileItem = (FileItem)it.next();

					if (fileItem.isFormField()){
						System.out.println ("- "+fileItem.getFieldName()+": "+fileItem.getString());
					} else{
						System.out.println ("- Name: "+ fileItem.getFieldName());
						System.out.println ("- Size: "+ fileItem.getSize());
						System.out.println ("- Value: "+ fileItem.getName());
						System.out.println ("- Content Type: "+ fileItem.getContentType());
						System.out.println ("- Extension: "+ fileItem.getName().substring(fileItem.getName().indexOf(".")));
						/*
						ServletContext sc = getServletConfig().getServletContext();
						String dir = sc.getRealPath("/");
						*/
						String dir = "/MyPath/MyProject/WebContent/";
						File myFile = new File(dir + fileItem.getName());
						fileItem.write(myFile);
						System.out.println ("- File Path: "+ myFile.getAbsolutePath());
					}
				}	

			}

		} catch (Exception e) {
			System.out.println ("Error:\n"+e);
		}
	}
}

Flex applications with file upload through HTTPS has a security violation problem accepted by Internet community and it has no easy solution.

Although there are workaround proposed by the flex community, it not ever work and finally it’s better to use Flex and HTML mixed solutions.

Then is interesting to use javascript libraries as Dojo and ExternalInterface class which Flex use to communicate with the browser.

Following there is a simple example:


Source codeClick with the right button to obtain source code.

Functionality doesn´t solve managing files because is a very common HTML implementation.

Inline itemRenderer/itemEditor using <mx:Component> tag.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
	<![CDATA[
		import mx.collections.ArrayCollection;

		[Bindable]
		private var items:ArrayCollection=new ArrayCollection([
			{col1:1,col2:0},
			{col1:2,col2:1}
		]);

	]]>
</mx:Script>

<mx:Component id="myInlineRenderer">
    <mx:ComboBox dataProvider="{labels}"
    	creationComplete="event.target.selectedIndex=data.col2"
    	change="item=event.target.selectedItem">
    	<mx:Script>
    		<![CDATA[
    			import mx.collections.ArrayCollection;
    			[Bindable]
    			public var item:Object;

    			[Bindable]
				private var labels:ArrayCollection=new ArrayCollection([
					{label:'label1',value:1},
					{label:'label2',value:2}
				]);
    		]]>
    	</mx:Script>
    </mx:ComboBox>
</mx:Component>

<mx:DataGrid id="dt" dataProvider="{items}" editable="true">
    <mx:columns>
        <mx:DataGridColumn dataField="col1" headerText="COL 1"
        	sortable="false" editable="false"/>
        <mx:DataGridColumn dataField="col2" headerText="COL 2"
        	sortable="false"
        	itemRenderer="{myInlineRenderer}"
        	rendererIsEditor="true"
        	editorDataField="item"/>
    </mx:columns>
</mx:DataGrid>

<mx:Text text="Selected Item: {dt.selectedItem.col2.label}"/>

</mx:Application>

ComboBoxPaginated is a Flex component which extends ComboBox class and allow data pagination to delimit records in the dropdown.

It’s useful to control big amount of data in a comboBox.


Source codeClick with the right button to obtain source code.

Creative Commons License
This blog is under Creative Commons licence, unless indicated otherwise.
Special thanks to Mark James for the icon set used in this blog.