Using WebObjects DirectActions – pt. 4

Calling a DirectAction with values from a WOHyperlink

In the last segment we looked at using a form to submit values into a DirectAction, this time we’ll look at binding values to a WOHyperlink.

According to Apple’s Dynamic Elements Reference, the bindings for a WOHyperlink are:

action, href, pageName, directActionName, actionClass, fragmentIdentifier, string, target, disabled, secure, queryDictionary

The bindings in bold are the ones we are interested in:

  1. directActionName – The name of the action minus "Action" (i.e. "helloWorld").
  2. actionClass – The name of the class containing the action (in our examples we’ve been using the default: "DirectAction").
  3. queryDictionary – A dictionary of key/value pairs to append to the URL.

Clear? OK, it’s time to get started. As always, we are going to extend the previous examples, so fire up your IDE and we’ll begin.

First, add a new WOHyperlink to the Main component (somewhere outside the form). Bind its directActionName to "hyper" and its actionClass to "DirectAction" (don’t forget the " "s).

Next, create the hyperAction that’s bound to our WOHyperlink. Add the following to the DirectAction class:

public WOActionResults hyperAction() {
    WOComponent page = pageWithName("Main");
    System.out.println("Hyperlink values: " + 
                       this.request().formValues());
    return page;
}

This is not complex code it just exposes what is happening when this action is called.

Build and run the application. When the Main page loads, click on the new hyperlink. The page should reload and you should see this in the console:

Hyperlink values: {}

Now, lets attach a value to the WOHyperlink. In WebObjects Builder select the WOHyperlink and invoke the inspector (cmd+1). Add a new binding (use the small [+] button in the upper right corner of the Inspector window, and select Add binding). Give it a binding of ?name and a value of "david". The Main.wod snippet for the WOHyperlink should look something like this:

Hyperlink1: WOHyperlink {
    ?name = "david";
    actionClass = "DirectAction";
    directActionName = "hyper";
}

Save the component and reload the page, click on the link again and you should see this in the console:

Hyperlink values: {name = ("david"); }

You can add additional key-value pairs to the WOHyperlink by repeating the Add binding step above or by directly editing the Main.wod. For instance, the following WOHyperlink .wod snippet:

Hyperlink1: WOHyperlink {
    ?age = "10";
    ?name = "david";
    actionClass = "DirectAction";
    directActionName = "hyper";
}

Results in this output:

Hyperlink values: {name = ("david"); age = ("10"); }

Alternately, we can add the values to the WOHyperlink all at once in by using the queryDictionary. Open the Main.java file and add the following method:

public NSDictionary hyperDictionary() {
    NSMutableDictionary dict = new NSMutableDictionary();
    dict.takeValueForKey("david", "name");
    dict.takeValueForKey("10", "age");
    return dict;
}

Delete the two bindings you added to the WOHyperlink in the last step, and bind the hyperDictionary method to the queryDictionary binding. The section of Main.wod for the WOHyperlink should look like this:

Hyperlink1: WOHyperlink {
    actionClass = "DirectAction";
    directActionName = "hyper";
    queryDictionary = hyperDictionary;
}

OK, were almost done, build and run the application once again. Click on the link and you should see the same entry in the console as above:

Hyperlink values: {name = ("david"); age = ("10"); }

At this point you should have pretty much everything you need to play with DirectActions. We’ve looked at how to configure your application, trigger an action, decipher a DirectAction URL, grab values from a form, pass values with your hyperlinks, and get the use of a session if you need one. Next time we’ll look at combining Component actions and DirectActions using a WORedirect.

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.

Apple Retail Store Yorkdale?

Granted I don’t have any inside information, but I was at the Yorkdale Shopping Centre for lunch today and they had a big sign that said "40 New Stores – Spring 2005". The area that used to be occupied by Sears (which has now moved to a new location at the other end of the mall), the old cinemas, and the little bit of parking lot in between is being turned into a new corridor of shopping. So, if the reports of a Toronto Apple Store are true, I guess that’s where it will be.