This article is going to show two different styles of edit screens that can be used with AJAX tables in WebDev. Both Popup Pages and Full Page edits via PageDisplay. In fact for the demo, I have added a check box control that determines which style of edit to use at run time!
For a preview of the end results of both styles you can what a quick video I made demoing both styles.
There was discussion on the group last night about trying to use PageDisplay to edit a record from an AJAX table, having a link in the table make the call to the edit form. At first it seemed that they were making it harder than it needed to be and we all know the groups mantra, “If it seems to hard you are doing it wrong”. But when I dug into it there are some challenges presented by AJAX and server versus browser code that make it a little harder than you would expect. Thanks to John Armstrong for first bringing this issue up, and also finding a post by Fabrice Harari that provided the hints to the technique shown.
Since the Page Display issue is what sparked this article I will show that method first. So why is this difficult in the first place you may be wondering? Well an AJAX table makes its calls via AJAX, which is a mixture of Server and Browser code. Whenever you try to make a call to PageDisplay from browser code for from server code running in AJAX mode, you get the proverbial raspberry telling you its not allowed. Normally this is pretty easy to get around by creating a hidden button and using execute process to press the button. That technique does not work here, because it is still in AJAX mode and the PageDisplay command will cause a run time error. John’s Googleing found a Post from Fabrice Harari that mentioned using a Timer to get around the issue. That seems a little cryptic and it took some playing to see how that would help, but it indeed is the key to this technique. The next challenge is communicating information between the browser and the server, I have mentioned this before in the CURE article, and in this instance we do have to use the technique of a hidden edit control to accomplish that.
To start with you just need to create a table control and make sure that it is set for AJAX mode. For this demo I used the Hawaii example and the Products table.
Add four columns to the table, the Product Name, Specification, Price and the ID and link them to the appropriate file items. Notice I made the ID hidden, it is just there to hold the ID for use inside the code later.
Next make the Product Name column a link by choosing the details tab for it. And Selecting Link column, I unchecked the “send the values” because that seems to cause some issues and I didn’t need it, and the Action is Run the code of a table row. In the example’s I posted last night I had this action set to running the code of the BTN_SetEditValue, but that required the timer to always be running on the page and didn’t give as much control over the process, it may require one extra line of code this way but I believe it opens up more possibilities as well.
Create an Edit Control (EDT_EditID), this will hold the value of the ID of the product that is going to be edited. Because this processing is bridging the gap between server and browser at several points we need a method of communicating between the two halves. This control accomplishes this. Notice that the type is Numeric and the Input Mask is all nines. Interestingly enough while testing I was having slightly different behavior that John was, and it turned out to be because he had his Input Mask like below and I had left mine has “as defined by the project”. That worked fine for the initial load of the page, but when returning to the page from the form (via the browser back button) it was causing me to be in loop. The reason is in the code you are about to see there is a test for IF EDT_EditID <> 0. Apparently on returning it was treating the edit control like a string and 0.00 was failing that test.
The next control needed is a hidden button (BTN_SetEditValue), the button will be executed when the user clicks on the link in the table and sets the edit control you just created, to the value of the selected record ID.
The Server Code for that button is below, Notice it is AJAX enabled. This was another area that John and I’s testing had some differences, he had difficulty making it work without being AJAX enabled. For me it seemed that because it was being executed as part of an AJAX process, it was being forced into AJAX mode regardless Either way you know the process will need to be ran in AJAX mode so its always best to specify it that way anyway. I guess I should mention here exactly what AJAX mode means. Normally anytime sever code like below is executed, then a full page load will take place, which would essentially reset the page, which is not what we want. In AJAX mode the code takes place without a reload of the page. It is a hybrid of Browser and Server code, and as you can see from this article sometimes it takes some experimenting to use it to your advantage.
One more hidden button (BTN_EditARecord) is needed. This button will be fired from the timer event and is what actual performs the PageDisplay statement. Because this button is being “pressed” by the timer procedure, it is taking place from the broswer side and not running inside the AJAX event, which is why you are able to make the call to PageDisplay without creating a run time error.
As mentioned the only code is the call to PageDisplay and this button is not set for AJAX. Notice the EDT_EditID control’s value is being passed to the EditProduct Page. Remember the edit control was set with the ID of the product to edit when the link was set (you will see that code shortly).
Now its time to tie it all together and create the timer procedure that is going to manage the process. First in the onload process create a browser variable named EditTimer, this will hold the ID of the timer that is created so that it can be stopped once its job is done.
The browser code for Row Selection is below. Remember when you set the Product Name column to be a link, you set it to run the Row selection code. Ignore the IF and PopupDisplay statements for now, they are for the other style. If you are just doing the PageDisplay style you only need the last two lines, which starts a timer, storing its ID in EditTimer, and “presses” the BTN_SetEditValue button, which as you know will move the ID column value into the hidden edit control. The timer will run the EditARecord timer every 1/100th of a second. You may be wondering why not just set the value of the edit control to the ID columns value in this code. Well the column variables are not available in browser code, so its another area where we use the trick of a hidden button to accomplish a mix of browser and server code.
The last step for this page is to create the EditARecord browser procedure that will be ran by the timer. This code just checks to see if there is a value in the hidden edit control, which there will be as soon as the BTN_SetEditValue button is “pressed”. Once there is a value, it “presses” the BTN_EditARecord button which will issue the PageDisplay to display the edit form. It then resets the Edit control to 0 and stops the timer, so if the visitor uses the browsers back button they won’t get into a loop that just keeps calling the form.
There is nothing fancy about Page_EditProduct, this article is about the different styles of edit pages, not about making them pretty. Its a simple page with 3 edit controls for the name, description and price and a save and cancel button.
And the entire code of the page is shown below. The page accepts the ID as a parameter. Remember your PageDisplay statement is passing the value of the edit control as a parameter. It uses that value to retrieve the record from the file and update the controls. A little note here, you may be wondering about the use of FileToScreen instead of FileToPage, reading the help files shows that they are both the same statement so for consistency and sanity I have adopted the practice of always using FileToScreen and ScreenToFile.
The save button moves the values of the controls back to the file, saves the record, and then displays the browse again, passing in the ID of the edited record. You will see how to use that shortly. The cancel button simply does a PageDisplay to get back to the browse without saving the record.
Back over on the Page_BrowseProducts, since you are passing back the value of the record just edited you need to add a few more lines of code to handle that. First in the Global declarations setup the page to accept the parameter. Notice the =0, that makes the parameter optional. So if you issues PageDisplay(Page_BrowseProducts) the page will run and inSysID will be 0. Without the =0, you would have a compile error and would need to make all your calls without a record ID be PageDisplay(Page_BrowseProducts,0). Not a big deal, but every little bit you do helps. And the guy that comes along behind you will be sure to appreciate it!
No in the initialization of the Page if an ID has been passed in that record is selected via the TableSelectPlus statement. TableSelectPlus accepts the subscript (row number) of the row to select. TableSeek Returns the row number of the row that matches the conditions specified, in this instance where col_id = insysid that was passed in.
That is all there is to using PageDisplay to edit a record from an AJAX table. But what if you want to use Popup Pages instead. Or maybe even get fancier and have a “short form” and “long form” of edit depending on the situation. Well Uncle Pete wouldn’t leave you out in the cold would he?
The first step is to create a check box control (CBOX_EditViaPopup) to set which style of edit to use.
The next step is to create a Popup Page on the Page_BrowseProducts.
I added a cell with a background gradient to the popup and then copy and pasted the controls from the Page_EditProduct page. The only change made to the descriptions of the controls was to change the cancel button to not issue any server commands, since with a popup we remain on the same page and there is no reason to subject the visitor to a complete page refresh when they press cancel.
The code behind the Save button changes slightly as well. It should be AJAX enabled and after saving the record it issues a TableDisplay statement, this repositions the table to the record just added and refreshes it with the changes made. Again there is no need to reload the page because with the Popup you never left the page.
There is also a line of Browser code for the save button to close the Popup. That statement is not allowed in server code.
As you probably guess the cancel button is just the browser code to close the popup.
You already saw the browser code for the row selection of the table above but here it is again. In this case the the Checkbox is on so the only line of code executed is the PopupDisplay that displays the Popup.
But there is one last piece of code needed. Remember Popups are really just hidden parts of you pages that were initialized when the page was initialized, so the controls need to be reinitialize with the values of the record to edit. This is done in the Row Selection Server process. You should recognize the code from the Page_EditProduct. It simple retrieves the record and moves the values to the controls. Two things to notice however are. This code is in AJAX mode (you don’t want a page refresh) and you are using the value of COL_ID, since this is server code it is available to you, there was no need to move it into a hidden edit control.
There you have it two different styles of editing records from an AJAX table or even a Hybrid using both. Hopefully you will make your pages a little pretty than the demo pages I showed !!!