New PHP Features in Flash Builder 4 - Part 3: Implicit Paging and Data Management
New PHP Features in Flash Builder 4 - Part 3: Implicit Paging and Data Management
Join the DZone community and get the full member experience.Join For Free
A true open source, API-first CMS — giving you the power to think outside the webpage. Try it for free.
In the second part of this series, we looked at using using Zend AMF and Flash Remoting. In this final part, we will explore implicit paging, inline editing and data management features in Flash Builder 4.
While it is easy to see just how more productive we can be thanks to Flash Builder 4, there is still a lot more left. As an example, in taking a closer look at the object I selected for the PHP service, you will find a couple interesting methods that do not map directly to the normal create, read, update and delete (CRUD) operations. There are two methods in particular that stand out and they are getItemsPaged() and count().
You see, even with the efficiency gained with AMF there is going to come a time where we have too many records to return in a single call. That breaking point will depend on your infrastructure, data complexity, and even end user machine requirements, but it will happen. The common solution to this is to implement a paging mechanism. This usually takes the place of "Next" and "Previous" buttons in your application with some fashion of page indicator. It also means more development time. And quite frankly, they are bulky and ugly.
The scroll bar is the natural paging mechanism with an up button for previous, a down button for next, and a thumb button for controlling the page.
The two additional methods found on the example object help Flash Builder implement paging for you. The getItemsPaged() method gets a start index, which is the primary key in the database (or other unique identifier), and the number of records to return for a given page. The count() method lets Flash Builder know how many records to expect in total, which in the end helps size the scroll bar more accurately.
To setup paging we will right-click on the getItemsPaged() method and select to "Enable Paging." A dialog will presented which will ask us for the primary key of the respective data. The wizard will also ask you if there is a "count" method, and what that method is on your object. With the wizard complete, you can now drag the getItemsPaged() method onto the DataGrid (or related data control) to get data populated with paging enabled for you.
The default page size is twenty (20) which is what will be presented in the DataGrid when the application is run. When the user scrolls beyond the twenty that are there, additional remoting calls (in this case) will be made to get the page of data appropriate to the position of the scroll bar thumb button. The burden to scale is now removed from the end user machine and placed on your infrastructure - which is a much better place to have to scale.
If you have millions of records, the user can now easily scroll through the entire data set, assuming of course that your database can handle the load.
So long as you've setup the appropriate request handlers, the paging features are not exclusive to Zend AMF and can even be used with HTTPService endpoints.
Updating Data in a Master-Detail Form
To this point all we have done is view data, but what about updating it? Flash Builder has this figured out for you as well.
With the DataGrid selected, and bound to a service call, we can right-click and select the option to "Generate Details Form." The dialog that appears will ask what data type the form will represent, but the default is a "Master Control" a la a master-detail form. You can also choose to make the form editable (the default) or not, and call a service to get the details if necessary.
When you click on the "Next" button you will be presented with the list of columns in your data type. These are all selected by default, which means that Flash Builder will generate a form field for each of them. You may want to deselect certain fields, such as primary keys, so the user does not get the chance to edit them down the road. Clicking on the "Finish" button will give you a complete form for the data, and in the case of a master-detail association, the fields are already populated.
When you run the application, and click around the records, you'll see the form update appropriately. When you update the form, you will see the DataGrid update. This is made possible by the new Flex 4 feature of two-way binding. There are a lot of other core changes to the Flex SDK proper that I have not even touched on here, that merit your time in reading the documentation. Okay, that is great and all, but we are still not updating our data, and that was the goal we are after.
To actually get the application to submit the data to the server for updating, it would probably be a good idea to provide the user with a means to say when updating should happen. Let us add a button with the label of "Save" to the application. With that "Save" button selected in Design View, you will see the an "On Click" event handler field exposed in the Property Inspector just waiting for you to fill it in.
You will also see a little pencil icon next to the field. Clicking on the pencil will reveal that Flash Builder can generate a blank event handler for you, or tie the event into a service call. That later option, the option to "Generate Service Call" sounds right up our alley since we already have an updateItem() method in place on our service. When selected, Flash Builder will prompt you to choose the method to call when the "Save" button is clicked.
When you select your update method, in this case updateItem() you'll be switch into Code View and expected to fill in the name of the variable that holds the data. If you think about it, we have done all of this data-centric development so far without ever really looking at any code, so you may be confused as to what variable name to provide. If you look in that "Declarations" section I mentioned earlier, you will see a "census" namespace decare a "Person" variable named "person." That "person" object is is the value we want to provide the service call.
protected function dataGrid_creationCompleteHandler(
getItemsPagedResult.token = censusService.getItemsPaged();
protected function button_clickHandler(event:MouseEvent):void
updateItemResult.token = censusService.updateItem( person );
fault="Alert.show( event.fault.faultString )"
Save your application and run it, and you will now have paging, a master-detail form, and the ability to save records by clicking on the "Save" button.
Inline Editing and Data Management
This is all good, but you may have noticed earlier when you were clicking around the DataGrid that it is already editable inline. We should probably take advantage of that feature, right? After all this is a "rich" internet application we are talking about here. And what about making changes to multiple records before committing the new values? Say for example if there were dependencies, or perhaps the user was offline? This is where a feature called "data management" comes into play.
In an remote procedure call (RPC) world we generally spend precious development time implementing calls for CRUD actions. What is worse though is that when dealing with the asynchronous nature of RPC, that we also have to spend time building handler methods for the results. Having just ten objects to work with can result in 100 different method that you will have to implement. That is five CRUD calls per object, plus five CRUD result handlers per object, times ten objects gives you 100 methods to write.
Data management builds an abstraction around the RPC calls and handlers for you. When enabled, it also monitors changes to the data and allows you to perform batch updates. If you dig deep enough (read: beyond the scope of this article) you will even find almost all of the RPC abstracted so completely that you only ever have to worry about the data model itself.
To get the data management capabilities, we have only to turn once again to the Data/Services panel, and select a method. In this case, I am going to keep moving ahead with the getItemsPaged() method. Using this method will give me the best of both worlds - the ability to effortlessly page through large data sets, and the ability to update data inline.
Right-click on the desired method and then select the option to "Enable Data Management." The dialog box that is presented will first ask you to select the unique identifier for the data type. Then Flash Builder will be expecting you to tell it what service methods you use for the various CRUD actions. The service abstractions have now been updated for you to include data management features.
Be warned that these methods will expect a specific signature. To get a better handle on the signatures, have Flash Builder generate the PHP stub object for you once, and either fill it out, or make sure your existing service objects have the same interface.
Now by default, when you change values in the editable DataGrid, you will be queuing up a batch of changes. To send those changes to the server, we will first have Flash Builder generate an event handler stub just as we did with the "Save" button earlier. In this case however, rather than call the updateItem() method for each change on the server, we simply call the commit() method on the service, and it handles getting all the changes over to the server.
If you run this application through the debug player, you can even use the new Network Monitor panel in Flash Builder to see the calls made for each of the changes.
Taking this one step further, let us add a "Revert" button and generate a stub handler for it as well. Inside this handler, we can call a revertChanges() method on the service to rollback any changes made since the last commit. To see this in action, run the application again and make some changes to the data in the DataGrid. This time do not click on the "Save" button, rather click the "Revert" button and watch all the data go back to its previous values. Again, this is just the tip of the iceberg for data management and there is a lot more there for you to explore.
protected function button_clickHandler( event:MouseEvent ):void
protected function button1_clickHandler( event:MouseEvent ):void
All things said and done, I suspect that at this point you have a solid appreciation for the productivity gains that Flash Builder 4 brings to PHP developers. We started off with a look at the new branding from Flex Builder to Flash Builder - a cosmetic, but important change. After taking a look at what used to be involved in making a service call, we spent the remainder of the time exploring the new data-centric development features for PHP developers. These powerful new capabilities are designed to work with most service endpoints ranging from XML-RPC to Zend AMF, which can even be deployed for you.
Regardless of the underlying service, if implemented with a little care, you now have an easy way to add not only paging but also data management. I would encourage you to explore the code generated by Flash Builder to better understand its architecture, and how you can customize the behavior by extending the provided classes. If you think you have got a good handle on all of this and are looking for more exploration of Flex 4, I would suggest taking a look at the new "states" architecture in MXML 2009 and/or getting a little deeper on the component architecture for skinning components.
Opinions expressed by DZone contributors are their own.