Using WebObjects DirectActions – pt. 3

Calling a DirectAction with values from a form

This is the 3rd in a series, part 1 is here and part 2 is here. We’ve looked at the composition of a DirectAction URL, and how to retrive passed values. This time we’re going to look at how to call a DA with values from a form.

We are going to extend the examples we used last time so fire up your IDE (Eclipse I hope) and lets get started.

First we need to modify our Main component, edit the Main.html so it looks like this:

<html>
<head>
    <meta name="generator" content="WOLips Core">
    <title>New</title>
</head>
<body bgcolor=#FFFFFF>
    <webobject name=Form1>
        Usrename: <input type=text name=username>
        <br />
        Password: <input type=password name=password>
        <br />
        <input type=submit>
    </webobject>
</body>
</html>

Change the Main.wod so it looks like this:

Form1: WOForm {
    directActionName = "helloWorld";
    actionClass = "DirectAction";
}

Save and run the application. After the Main page loads, enter values in the two form fields and hit the submit button. You should see something like this in the console:

Form Values: {password = ("pass"); username = ("dave"); }

A couple of things to note: The only WO component on this page is the WOForm, it is bound to the helloWorld directActionName, and the DirectAction actionClass. All of the other form elements are just plain HTML.

You’ll also notice that the text field values are not retained – after you submit the form the text fields are blank. Lets look at how we might fix that:

  1. In WebObjectsBuilder convert the text fields to WOTextFields by clicking on the Make Dynamic button in their Inspector windows.
  2. Add a username and password variable of type String to your Main.java
  3. Bind the username variable to the username WOTextField, and the password variable to the password WOTextField
  4. Modify the helloWorldAction in the DirectActionclass so it looks like this:
public WOActionResults helloWorldAction() {
    NSDictionary dict = this.request().formValues();
    System.out.println("DA values: " + dict);
    WOComponent page = pageWithName("Main");
    String username =
        (String)this.request().formValueForKey("username");
    String password = 
        (String)this.request().formValueForKey("password");
    page.takeValueForKey(username, "username");
    page.takeValueForKey(password , "password");
    return page;
}

Now when we build, run, and submit the form, the form values should be retained. This little example shows how to grab the values from a form, and pass them to a page.

Before we go, lets try a little experiment, add a WOString to your Main component and bind it to session.sessionID (WOBuilder may complain that the This binding value is not defined – just click the Don’t Add button and move on).

When you are done, reload the Main page and submit the form a couple of times. What happens? If everything is working you should see something like the following appended to the URL:

wosid=e3ef6ofP1badQRlQtJdIew

Note: This will only work if you haven’t set setStoresIDsInCookies(true); and setStoresIDsInURLs(false); in your Session constructor.

wosid stands for WO Session ID and this demonstrates the mechanism that DirectActions use to track a Session. So, although you don’t need to trigger a Session from your DirectActions (you are free to manage state yourself) you can get one just by asking for it. This can be very helpful as we will see later.

Comments

12 Comments so far. Comments are closed.
  1. Kol. Panic,

    I was doing some Direct Action stuff today, and wanted to find a way to suppress the “&wosid=e3ef6ofP1badQRlQtJdIew” from my DA URLs. In case it helps someone (and Google finds this comment – Jenna Jameson BitTorrents :) ), here’s my solution.

    Just add a binding ?wosid to the DA WOHyperlink with a value no. Your component’s .wod file should then contain something like this:


    Hyperlink1: WOHyperlink {
        directActionName = "myAction";
        queryDictionary = myQueryDictionary;
        ?wosid = no;
    }

  2. Thanks KP.

    I take it you don’t need access to the Session from your DA then.

  3. Kol. Panic,

    No Session needed. I wanted to provide a bookmarkable hyperlink to directly access a particular page.

  4. Was running through these tutorials today, and I must say they are great. I have been using WO for 3 years now and never really got into DA’s.

    Anyway, I was interested in the wosid appending to the URL and I could not get this working unless it commented out the line :

    setStoresIDsInURLs(false);

    in Session.java.

    I couldn’t find any reference to this in your tutorial, so I was wondering if this is the case.

  5. david,

    Sorry about that Andrew,

    Yeah, if you have setStoresIDsInCookies(true); and setStoresIDsInURLs(false); in your Session constructor you will get a sessionID, but you won’t see it in the URL (because it will be stored in the browsers cookie).

    I’ll make that clearer…

  6. Mc,

    I tried this out and it does not work. The variables are not being parsed on to the next page. If you were to use other variables such as myUsername and myPassword in the helloWorld action, nothing shows. Likewise, if you returned another page called test the variables are not parsed on to that page.

  7. david,

    Mc,

    What does the console message generated by the System.out.println("DA values: " + dict); line look like?

  8. Mc,

    I am using an apple ibook and there was no console. When I use your code as is, everything works fine. Then I created a new page called “ThankYou”, created the two variables username and password and I bind them to two WOStrings, and substituted “Main” for “ThankYou”. When I clicked the submit button the “ThankYou” page did not open but the changes took place on the “Main” page. I then created a WOHyperlink calling the “helloWorld” action (just as the submit button) and this time the “ThankYou” page opened but with no username and password values. To verify whether the vaiables were being passed to any page I decided to use different names for the variables to avoid any ambiguities and hence ammended the code as follows:

    public WOActionResults helloWorldAction() {
    NSDictionary dict = this.request().formValues();
    System.out.println(“DA values: ” + dict);
    String username1 = (String)this.request().formValueForKey(“username”);
    String password1 = (String)this.request().formValueForKey(“password”);
    WOComponent page = pageWithName(“Main”);
    page.takeValueForKey(username1, “myUsername”);
    page.takeValueForKey(password1, “myPassword”);
    return page;
    }

    My intention was to pass the username and password values to myUsername and myPassword. That did not work. My goal is to pass form values from one page to another. I’m new to WebObjects so any assistance you provide is very much appreciated. Let me know if my code makes any sense and what corrections should I make.

    ThanK You

  9. david,

    Mc,

    A couple things:

    1. A hyperlink will call the action but will not submit the form (So no form values will be sent to the DirectAction). That is an HTML thing.

    2. The console I’m referring to is the run log for the App in Xcode or Eclipse.

    3. You say you are new to WebObjects. Have you worked through the Apple Web Applications tutorial? These examples are for DirectActions and they assume a familiarity with the WebO fundamentals covered in that guide.

    4. I don’t know why your ThankYou page was not opening before you implemented the WOHyperlink, I would suspect a mistyped literal string somewhere.

  10. Mc,

    Hi David,

    I found my error, I missed out the directaction on the WOForm. I added the following code:

    System.out.println(“DA values: ” + dict);
    System.out.println(“Username: ” + this.request().formValueForKey(“username”));
    System.out.println(“Password: ” + this.request().formValueForKey(“password”));

    and the reults in the console were:

    DA values: {5.1 = (“Mc. Colin”); 5.3 = (“password”); WOSubmitAction = (“helloWorld”); helloWorld = (“Submit”); }
    Username: null
    Password: null

    So, the two values are being passed in the this.request().formValues() but not the this.request().formValueForKey(“username”). How can I resolve this or what should I do???

    Thanks for your help…

    Mc.

  11. Ken,

    It seems that when you use WOTextField in your HTML file you still need to supply the key via a name attribute. Otherwise WO will generate it’s own key and it won’t always be the same.

    For example, instead of:

    try:

    That works for me every time,

    Ken

  12. Ken,

    Sorry…obviously it translated my code. Let’s try this again.

    Instead of:


    try: