as3 print a page with text, image and data grid [closed] - actionscript-3

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I have an AIR application.
I want to print a set of text, image and datagrid my document is like a report.
As datagrid has different heights, I don't know how to do.
Could you help me ?
Best regards

Here's an example from the docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/printing/FlexPrintJob.html
FormPrintFooter.mxml
<s:VGroup name="FormPrintFooter"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
width="60%"
horizontalAlign="right" >
<!-- Declare and initialize the product total variable. -->
<fx:Script>
<![CDATA[
[Bindable]
public var pTotal:Number = 0;
]]>
</fx:Script>
<s:Label text="Product Total: {pTotal}"/>
</s:VGroup>
FormPrintView.mxml
<!-- Custom control to print the Halo DataGrid control on multiple pages. -->
<s:VGroup name="FormPrintView"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns="*">
<fx:Script>
<![CDATA[
import mx.core.*;
// Declare and initialize the variables used in the component.
// The application sets the actual prodTotal value.
[Bindable]
public var pageNumber:Number = 1;
[Bindable]
public var prodTotal:Number = 0;
// Control the page contents by selectively hiding the header and
// footer based on the page type.
public function showPage(pageType:String):void {
if (pageType == "first" || pageType == "middle") {
// Hide the footer.
footer.includeInLayout = false;
footer.visible = false;
}
if (pageType == "middle" || pageType == "last") {
// The header won't be used again; hide it.
header.includeInLayout = false;
header.visible = false;
}
if (pageType == "last") {
// Show the footer.
footer.includeInLayout = true;
footer.visible = true;
}
//Update the DataGrid layout to reflect the results.
validateNow();
}
]]>
</fx:Script>
<!-- The template for the printed page, with the contents for all pages. -->
<s:VGroup width="80%" horizontalAlign="left">
<s:Label text="Page {pageNumber}"/>
</s:VGroup>
<FormPrintHeader id="header" />
<!-- The data grid. The sizeToPage property is true by default, so the last
page has only as many grid rows as are needed for the data. -->
<mx:PrintDataGrid id="myDataGrid" width="60%" height="100%">
<!-- Specify the columns to ensure that their order is correct. -->
<mx:columns>
<mx:DataGridColumn dataField="Index" />
<mx:DataGridColumn dataField="Qty" />
</mx:columns>
</mx:PrintDataGrid>
<!-- Create a FormPrintFooter control and set its prodTotal variable. -->
<FormPrintFooter id="footer" pTotal="{prodTotal}" />
</s:VGroup>
PrintDataGridExample.mxml
<!-- Main application to print a Halo DataGrid control on multiple pages. -->
<s:Application name="PrintDataGridExample.mxml"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
initialize="initData();">
<fx:Script>
<![CDATA[
import mx.printing.*;
import mx.collections.ArrayCollection;
import FormPrintView;
import mx.core.FlexGlobals;
// Declare variables and initialize simple variables.
[Bindable]
public var dgProvider:ArrayCollection;
public var footerHeight:Number = 20;
public var prodIndex:Number;
public var prodTotal:Number = 0;
// Data initialization.
public function initData():void {
// Create the data provider for the DataGrid control.
dgProvider = new ArrayCollection;
}
// Fill the dgProvider ArrayCollection with the specified items.
public function setdgProvider(items:int):void {
prodIndex=1;
dgProvider.removeAll();
for (var z:int=0; z<items; z++) {
var prod1:Object = {};
prod1.Qty = prodIndex * 7;
prod1.Index = prodIndex++;
prodTotal += prod1.Qty;
dgProvider.addItem(prod1);
}
}
// The function to print the output.
public function doPrint():void {
var printJob:FlexPrintJob = new FlexPrintJob();
if (printJob.start()) {
// Create a FormPrintView control as a child of the current view.
var thePrintView:FormPrintView = new FormPrintView();
FlexGlobals.topLevelApplication.addElement(thePrintView);
//Set the print view properties.
thePrintView.width=printJob.pageWidth;
thePrintView.height=printJob.pageHeight;
thePrintView.prodTotal = prodTotal;
// Set the data provider of the FormPrintView component's data grid
// to be the data provider of the displayed data grid.
thePrintView.myDataGrid.dataProvider = myDataGrid.dataProvider;
// Create a single-page image.
thePrintView.showPage("single");
// If the print image's data grid can hold all the provider's rows,
// add the page to the print job.
if (!thePrintView.myDataGrid.validNextPage) {
printJob.addObject(thePrintView);
}
// Otherwise, the job requires multiple pages.
else {
// Create the first page and add it to the print job.
thePrintView.showPage("first");
printJob.addObject(thePrintView);
thePrintView.pageNumber++;
// Loop through the following code until all pages are queued.
while (true) {
// Move the next page of data to the top of the print grid.
thePrintView.myDataGrid.nextPage();
thePrintView.showPage("last");
// If the page holds the remaining data, or if the last page
// was completely filled by the last grid data, queue it for printing.
// Test if there is data for another PrintDataGrid page.
if (!thePrintView.myDataGrid.validNextPage) {
// This is the last page; queue it and exit the print loop.
printJob.addObject(thePrintView);
break;
} else {
// This is not the last page. Queue a middle page.
thePrintView.showPage("middle");
printJob.addObject(thePrintView);
thePrintView.pageNumber++;
}
}
}
// All pages are queued; remove the FormPrintView control to free memory.
FlexGlobals.topLevelApplication.removeElement(thePrintView);
}
// Send the job to the printer.
printJob.send();
}
]]>
</fx:Script>
<s:Panel title="DataGrid Printing Example"
width="75%" height="75%"
horizontalCenter="0" verticalCenter="0">
<s:VGroup left="10" right="10" top="10" bottom="10">
<mx:DataGrid id="myDataGrid" dataProvider="{dgProvider}">
<mx:columns>
<mx:DataGridColumn dataField="Index"/>
<mx:DataGridColumn dataField="Qty"/>
</mx:columns>
</mx:DataGrid>
<s:Label width="100%" color="blue"
text="Specify the number of lines and click Fill Grid first. Then you can click Print."/>
<s:TextInput id="dataItems" text="35"/>
<s:HGroup>
<s:Button id="setDP" label="Fill Grid" click="setdgProvider(int(dataItems.text));"/>
<s:Button id="printDG" label="Print" click="doPrint();"/>
</s:HGroup>
</s:VGroup>
</s:Panel>
</s:Application>

Related

Flex 4 - How to use filter for NumericStepper?

I have an XML file Which contains Employee details . And I have to use filter on it. Here, I want to filter the experience using two NumericStepper. If I select 1 and 4 for first and second NumericStepper, DataGrid Will display the employee list which are the employee's has experienced between 1 to 4.
Here my code:
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.FlexEvent;
import mx.utils.ObjectUtil;
private function xmlListCollectionFilterFun(item : Object) : Boolean
{
if(employeeName.text.length !=0)
{
if((item.Name).toLowerCase().indexOf(employeeName.text.toLowerCase())!= -1)
{
return true;
}
}
if(employeeID.text.length != 0)
{
if((item.Id).toLowerCase().indexOf(employeeID.text.toLowerCase()) != -1)
{
return true;
}
}
if(endYear.value != 0)
{
if((startYear.value)<=(item.Experience)<=(endYear.value))
{
return true;
}
}
return false;
}
protected function employeeText_changeHandler():void
{
if( employeeName.text.length == 0 && endYear.value == 0 &&
employeeID.text.length == 0 )
{
employeeXMLList.filterFunction = null;
}
else
{
employeeXMLList.filterFunction = xmlListCollectionFilterFun;
}
employeeXMLList.refresh();
}
]]>
</fx:Script>
<fx:Declarations>
<fx:XML id="tempXML"
source="skins/TextXmlFile.xml" />
<s:XMLListCollection id="employeeXMLList"
source="{tempXML.Employee}" filterFunction="xmlListCollectionFilterFun"/>
</fx:Declarations>
<s:layout>
<s:VerticalLayout verticalAlign="top" horizontalAlign="center" paddingTop="30"/>
</s:layout>
<mx:VBox width="100%">
<s:HGroup width="100%">
<s:TextInput id="employeeName" change="employeeText_changeHandler()" prompt="Employee Name"/>
<s:TextInput id="employeeID" prompt="Employee ID" change="employeeText_changeHandler()"/>
<s:NumericStepper id="startYear" minimum="0" maximum="50" snapInterval="1" />
<s:NumericStepper id="endYear" minimum="0" maximum="50" snapInterval="1" change="employeeText_changeHandler()"/>
</s:HGroup>
<s:DataGrid id="dataGrid" dataProvider="{employeeXMLList}" width="100%" height="100%">
<s:columns>
<s:ArrayCollection>
<s:GridColumn id="nameCol" dataField="Name" headerText="Name:"/>
<s:GridColumn id="idCol" dataField="Id" headerText="ID:"/>
<s:GridColumn id="experienceCol" dataField="Experience" headerText="Experience:"/>
</s:ArrayCollection>
</s:columns>
</s:DataGrid>
This is code is no effect for NumericStepper. If anyone can find my mistake?
Try always to split your code in small functions that do a single thing, I would do it like this:
getUserExperience(user:Object):Number
implement this function first do some test and after you get it o return the correct experience then you can go to the next step to make the filter function.
Write some code to compute the min and max experience for the filter
var min:Number=startYear.value;
var max:Number=endYear.value;//if needed adjust this to seome default values
now the filtering should be easy because you just have numbers and no UI components and Objects
so the filter will need to check a simple thing
var userExp:Number=getUserExperience(user);
var response:Boolean=mio<=userExp&&userExp<=max;
return response;
I am sure after you refactor your code to be simple and clear it will be easy to fix any bugs
Is it a typo in your code or a problem with stack overflow that doesn't display some chars (the OR pipes I assume) ?
employeeName.text.length == 0 endYear.value == 0 &&
employeeID.text.length == 0
update: even with pipes, this test does not make sense.

Spark.Components.List with variable content: Flex 4, AS3

I coded the following in Flex 4/AS3 and it doesn't worked as expected.
So, I would like to know if there is something wrong with my code... I'll explain it:
TileTest.mxml
<s:Application minWidth="955" minHeight="600" creationComplete="createButtons()"
<fx:Script>
<![CDATA[
import Object.TestButton;
import mx.collections.ArrayList;
private var _names:Array = ["one", "two", "three"];
public function createButtons():void
{
var buttons:ArrayList = new ArrayList();
for(var a:int = 0; a < _names.length; a++)
{
var testButton:TestButton = new TestButton();
testButton.customName = _names[a];
buttons.addItem(testButton);
}
myList.dataProvider = buttons;
}
]]>
</fx:Script>
<s:VGroup gap="12" width="100%">
<s:Label text="Options" fontSize="18" fontWeight="bold" color="#333333" />
<s:List width="100%" height="100%" id="myList" itemRenderer="Object.TestButton" borderVisible="false">
<s:layout>
<s:TileLayout orientation="rows" columnWidth="290" rowHeight="90" columnAlign="left" horizontalGap="0" verticalGap="0" />
</s:layout>
</s:List>
</s:VGroup>
</s:Application>
This is my Application. Here, I have a List called myList, where I load some TestButtons. I set a name for each button inside the loop.
TestButton
<s:Group width="300" height="90" click="{ Alert.show(_name); }"
<fx:Script>
<![CDATA[
import mx.controls.Alert;
private var _name:String = "just a test...";
public function set customName(newName:String):void
{
_name = newName;
Alert.show(_name);
this.addEventListener(MouseEvent.MOUSE_OVER, function():void{ Alert.show(_name); });
}
]]>
</fx:Script>
<s:BorderContainer accentColor="#000000" width="100%" height="100%" />
</s:Group>
As you can see, I have three Alerts in this component... I did so we can understand the problem.
The first Alert occurs when I set the customName, which occurs in the Application, as already shown.
The second one should occur on Mouse_Over, as the event listener been added to the Group element.
And the third Alert should occur on Click in the Group element.
Now, if I run the resulting swf, I see all the three buttons in the screen and three Alerts, one for each set customName by the Application and it alerts the right name.
If I put the mouse over any button, it doesn't alert any message.
If I click any button, it alerts the default message set to the _name property, which is "just a test..."
I can't understand what is the problem, as I was expecting it to always alert the name set by the Application to each button. Also, I don't want to change the components... what I'm saying is that I would like to have a List and TestButtons with a private String inside.
If the problem is in these specific implementation, so I'll have no other way than change it...
Thank you all!
The problem is that you have a list of TestButtons in your data provider, instead of just plain data. Those buttons get created, and that is why you see the correct Alert messages.
So, then Flex sees a list with three items and therefore it creates three additional TestButtons to render the data in your list. But those TestButtons are completely new ones, with default values for its properties.
To fix this, it would be better if you had data only in your data provider ArrayList, and you would access it through the data property of your item renderer.

"Flexicious" : not able to change the search functionality dynamically in a data Grid

"Flexicious" a third party component library built for handling very larg data set in DataGrid for flex, The issue is, i am not able to change the search functionality dynamically in a data Grid.
<flxs:FlexDataGridColumn id="multiselect" dataField="Name" headerText="Name"
filterControl="NumericTextInput" headerAlign="center">
<flxs:headerRenderer>
<fx:Component>
<controls:ComboBox change="changeSel(event)" width="10" height="41" dataProvider="outerDocument.searchArray}">
<fx:Script>
<![CDATA[
import com.flexicious.controls.ComboBox;
import mx.controls.Alert;
public function changeSel(event:Event):void{
var cbox:ComboBox = event.currentTarget as ComboBox;
if(cbox.selectedItem=="Less Than"){
outerDocument.multiselect.filterOperation="LessThanEquals";
//Alert.show(""+outerDocument.multiselect.filterOperation);
}else if(cbox.selectedItem=="Greator Than"){
outerDocument.multiselect.filterOperation="GreaterThanEquals";
//Alert.show(""+outerDocument.multiselect.filterOperation);
}else if(cbox.selectedItem=="Equal To"){
outerDocument.multiselect.filterOperation="Equals";
//Alert.show(""+outerDocument.multiselect.filterOperation);
}else if(cbox.selectedItem=="Begins With"){
outerDocument.multiselect.filterOperation="BeginsWith";
//Alert.show(""+outerDocument.multiselect.filterOperation);
}
}
]]>
</fx:Script>
</controls:ComboBox>
</fx:Component>
</flxs:headerRenderer>
</flxs:FlexDataGridColumn>
Now when i select any option from the rendered combobox i am not able to change filteroption, however when i alter the filteroperation it dose show me the changed operatioin but in functionality it doesn't change.
You should call grid.rebuildFilter() after changing the filterOperation

View Navigator Hide Specific Tab Not TabBar

I'm trying to figure out whether it is possible to define view navigators and selectively hide some depending on a particular user state?
For example I have two navigator tabs one which is a sign in tab and the other shows a users policy. I only want the policy tab to be visible if the user has signed in:
<s:ViewNavigator id="policyTab" width="100%" height="100%" firstView="views.policy.PoliciesView">
<s:navigationContent>
<s:Button id="policyTabButton" label="Policies" click="tabButton_clickHandler(event)" />
</s:navigationContent>
</s:ViewNavigator>
Sign in tab is navigator:
<s:ViewNavigator id="signInTab" width="100%" height="100%" firstView="views.SignInView">
<s:navigationContent>
<s:Button id="signInTabButton" icon="#Embed('images/lockSmall.png')" click="tabButton_clickHandler(event)" />
</s:navigationContent>
</s:ViewNavigator>
Everything that I've researched points me to hiding the entire tab bar which I don't want to do. I've tried simply calling signInTab.visible = false; but is doesn't work.
Any help would be appreciated.
It is true that you can't hide the contents of a TabbedViewNavigator, but there is another way to adjust the content to hide tabs. Basically you can remove the tab from the TabbedViewNavigator to hide it and re-add it to show it again. I've come up with a very simple example which seems to do what you are asking.
TabbedViewNavTest.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:TabbedViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
applicationDPI="160"
preinitialize="preinitializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import views.Tab2View;
private static var app:TabbedViewNavigatorApplication;
public static function adjustTabBar():void {
if(app.navigators.length > 1) {
removeTab2();
} else {
addTab2();
}
}
private static function removeTab2():void {
app.tabbedNavigator.removeItemAt(1);
}
private static function addTab2():void {
var tab2:ViewNavigator = new ViewNavigator();
tab2.label = "Tab2";
tab2.percentWidth = 100;
tab2.percentHeight = 100;
tab2.firstView = Tab2View;
app.tabbedNavigator.addItemAt(tab2, 1);
}
protected function preinitializeHandler(event:FlexEvent):void {
app = this;
}
]]>
</fx:Script>
<s:ViewNavigator id="tab1" label="Tab1" width="100%" height="100%" firstView="views.Tab1View"/>
<s:ViewNavigator id="tab2" label="Tab2" width="100%" height="100%" firstView="views.Tab2View"/>
</s:TabbedViewNavigatorApplication>
Tab1View.mxml:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Tab1">
<fx:Script>
<![CDATA[
protected function showHideButton_clickHandler(event:MouseEvent):void {
TabbedViewNavTest.adjustTabBar();
}
]]>
</fx:Script>
<s:Button id="showHideButton" label="Click Me!" click="showHideButton_clickHandler(event)" />
</s:View>
Tab2View is just an empty view that was created when I created the project.
While this should do what you need it to do, I'm wondering if there is a better way to achieve what you are attempting to do. For instance, in the case you originally presented of a login tab which disappears when the user logs in you could have created your application as a generic application with 2 states: notLoggedIn and loggedIn. In the notLoggedIn state you only have a view show that presents the login screen, or have a tabbedViewNavigator show which has the login and policy tabs. In the logged in state, you have a separate tabbedViewNavigator which has only the policy tab or perhaps the other tabs available when a user is logged in. If you want me to create an example of what I mean, let me know and I can do that.

I call Alert.Show in a function and want to get the result from there (Flex, ActionScript)

I'm using the Alert.show in a function and I want to get the user answer from there. So how can I achieve this. The problem is the function that call Alert.show will return a true or false value depend the user answer.
but It seem that in Alert.show it only allow to pass in a CloseHandler for this. that is a new function. and since that I can get the user answer from where it is call to return the user answer.
Really thanks for help
Yuan
Try this code
<?xml version="1.0" encoding="utf-8"?>
<!-- Simple example to demonstrate the Halo Alert control. -->
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.events.CloseEvent;
// Event handler function uses a static method to show
// a pop-up window with the title, message, and requested buttons.
private function clickHandler(evt:Event):void {
Alert.show("Do you want to save your changes?", "Save Changes", Alert.YES|Alert.NO, this, alertClickHandler);
}
// Event handler function for displaying the selected Alert button.
private function alertClickHandler(evt:CloseEvent):void {
if (evt.detail == Alert.YES) {
status.text = "You answered Yes";
} else {
status.text = "You answered No";
}
}
// Event handler function changes the default Button labels and sets the
// Button widths. If you later use an Alert with the default Buttons,
// you must reset these values.
private function secondClickHandler(evt:Event):void {
Alert.buttonWidth = 100;
Alert.yesLabel = "Magenta";
Alert.noLabel = "Blue";
Alert.cancelLabel = "Green";
Alert.show("Select a color:", "Color Selection", Alert.YES|Alert.NO|Alert.CANCEL, this);
// Set the labels back to normal:
Alert.yesLabel = "Yes";
Alert.noLabel = "No";
}
]]>
</fx:Script>
<s:Panel title="Halo Alert Control Example"
width="75%"
horizontalCenter="0" verticalCenter="0">
<s:VGroup left="10" right="10" top="10" bottom="10">
<s:Label color="blue"
text="Click the button below to display a simple Alert window."/>
<s:Button label="Click Me" click="Alert.show('Hello World!', 'Message');"/>
<mx:HRule width="100%" />
<s:Label color="blue"
text="Click the button below to display an Alert window and capture the button pressed by the user."/>
<s:Button label="Click Me" click="clickHandler(event);"/>
<s:Label id="status" fontWeight="bold"/>
<mx:HRule width="100%" />
<s:Label color="blue"
text="Click the button below to display an Alert window that uses custom Button labels."/>
<s:Button label="Click Me" click="secondClickHandler(event);"/>
</s:VGroup>
</s:Panel>
</s:Application>
You can do this.
here's how:
private function deleteItem_Confirmation_Handler(event:CloseEvent):void
{
if(event.detail == Alert.OK)
{
//Your code here
}
}
public function deleteValue():void
{
Alert.show("Are you sure you want to delete this item?", "confimation", Alert.OK | Alert.CANCEL, null, deleteItem_Confirmation_Handler, null, Alert.OK);
}
change
evt.detail == Alert.YES
to
evt.detail == 1
the yes button returns an int value of 1, the no button would return an int value of 2