June 9, 2012

Dealing with Forms in 6.4.5

Usually, an increment from 6.4.4 to 6.4.5 would contain bug fixes only. However, one very small feature was added to this release. Its the LiveForm onBeforeServiceCall event.

Background

A few weeks before 6.4.5 shipped, I was working on a project. I was handed a database, and each table in the database had the following fields:

  • createdAt (java.util.Date)
  • updatedAt (java.util.Date)

This seemed like a perfectly reasonable database design until I started trying to set these values in a LiveForm. A LiveForm lets you bind an editor’s value using defaultInsert so that you can control the values of createdAt and updatedAt when inserting a new entry with a simple bind expression:
new Date().getTime()

But how do we update the createdAt field when the user edits an entry in the LiveForm?

  • You can not bind it. binding dataValue or defaultInsert has no effect on trying to update an existing form value
  • You probably will want to hide or keep this editor uneditable
  • You might even want to delete this editor, since a user isn’t supposed to change the updatedAt value
    • However, all of the LiveForm logic that takes the editor values, and sends them to the server as an insert or update operation is hidden; there is no entry point at which you can change what is being sent.

      I certainly considered creating custom events for each and every save button throughout the application so that the save button would change the value of a hidden editor, and then call the LiveForm’s saveData method.

      The new event

      Instead, I concluded that this was much more work than it should have been. I wanted the project I was working on to be simple, easy to understand and maintainable. It was clear that users of WaveMaker needed a way to change any values that needed changing before they could be sent to the server. That is the background of the onBeforeServiceCall event; below we go into more detail on how to use it.

      Using the onBeforeServiceCall event, you can review all values that are being sent to the server, validate them if needed, fix those that need fixing, and when your done, let the LiveForm finish its save operation.

      liveForm1BeforeServiceCall: function(inSender, inOperation, inData) {
            if (inOperation == "update") {
      
                 /* inData is a standard javascript Object, not a wm.Variable;
                  * do NOT use setValue or getValue on inData
                  */
                 inData.updatedAt = new Date().getTime();
                 if (inData.createdAt > inData.updatedAt) {
                      app.toastError("Invalid value for createdAt");
                      throw new Error("Abort");
                 }
            }
        }

      The LiveForm gathers all of the values it will send to the server and puts them into inData. It then calls onBeforeServiceCall allowing you to make any changes you need to make to inData. After the event handler has finished, the modified data is sent to the server.

      What does all of this mean? In the past, LiveForm was a black box that you had to bend over backwards to get to work if you have any special needs. This new event handler allows you to take control of what the form sends to the server.

      Did this make my project more maintainable? Using the “shared javascript” function, I was able to make All of my LiveForms use the above event handler; I wronte one event handler for updating all of the updatedAt values, and all of my forms use that one method. Yes, this is a lot more maintainable.

      The evolution of forms in 6.5

      In Wavemaker 6.5, we introduce a new set of Form widgets called DataForm and DBForm. These new form widgets are comparable in many ways to LiveForm, but let you take control:

      • You can bind the form’s dataOutput. After the form finishes transfering all of the editor values to the form’s dataOutput, your bindings are then evaluated, and only after your bindings have been evaluated does the form send the data to the server. Your binding takes precedence over any values in your editors; typically, your bind expression would have the editor’s value in it, but in the case of updatedAt, all you need is the bind expression new Date().getTime().
      • The new forms no longer use defaultInsert. Instead, you simply bind the editor’s dataValue, and this value shows in the editor when the user hits “New”. You can also tell each editor to use this binding when the user hits “Edit”.
      • Note that this form will be in beta for a while; LiveForm has been around for a while, its reliable; we’re not looking to lose it any time soon. We just want to see if there are better ways to do things, and allow those who dare to experiment with these new ways of doing things

      Michael Kantor; SMTS
      VMware, WaveMaker team

      Facebook Twitter Linkedin Digg Delicious Reddit Stumbleupon Email
Comments (3)  Filed under: WaveMaker — Michael Kantor @ 11:07 pm

3 Comments »

  • Very interesting, but one question.
    For things like this, It’s not suppose to be better to introduce this logic in the model layer? I mean, in setUpdateAt method of java class?

    Regards.

    Comment by Giu — June 10, 2012 @ 3:05 am

  • For purposes of defining behaviors for a specific field like updatedAt? Perhaps. For purposes of putting you in control of your form? No, the model is rarely precise enough to do all of the things you’re likely to want to do. My goal was to put you in control and make the environment less of a black box whose logic you can’t touch, not to put the model in control and leave the black box in place.

    Michael

    Comment by Michael Kantor — June 11, 2012 @ 11:21 am

  • I have it more clear now, thanks.

    Comment by Giu — June 11, 2012 @ 12:42 pm

RSS feed for comments on this post.   TrackBack URL


Leave a comment

Social links powered by Ecreative Internet Marketing