Table of Contents Previous Section

Add a detail display group to the details page

In the previous section, you navigated relationships to access attributes in other entities. Using the movieRoles relationship in the Movies entity, you were able to display attributes of a movie's roles. Similarly, you displayed the names of the actors who played a role by navigating two relationships: movieRoles to get from a movie to one of its roles and talent to get from the role to the actor who played it. Traversing the object graph this way works very well in read-only scenarios where you only want to display information in a related object. However, it doesn't work completely in scenarios where you want to be able to make changes to the related objects.

In the next section, you'll give the application the ability to insert, update, and delete movie roles for the selected movie. This read-write scenario requires a slight modification to the way you access movie role information. To be able to insert new movie roles for a movie, you need a WODisplayGroup for managing MovieRole objects.

Disconnect the bindings

  1. Inspect the repetition.

  2. Disconnect the list binding.

  3. Disconnect the item binding.

  4. Similarly, disconnect the value bindings for each of the three string elements.

Delete the movieRole variable

  1. Select the movieRole variable in the object browser.

  2. Click the delete button.

    Recall that the movieRole variable was created automatically when you bound movies movieRoles to the repetition's list attribute. Since you disconnected the list and item bindings, you don't need the movieRole variable anymore.

Create a second WODisplayGroup

  1. Drag the MovieRole entity from your model file into the MovieDetails component window.

    WebObjects Builder creates a variable named movieroles in the MovieDetails component. movieroles is a WODisplayGroup that manages MovieRole objects.

Set up a master-detail relationship

As is, the movieroles display group manages all the movie roles in the database, but it should manage only the MovieRole objects that are related to the selected movie. To restrict the objects that movieroles manages, you need to set up a master-detail relationship between the movieroles and movies display groups.

  1. Add the following init method to MovieDetails' script:
    	- init {
    		[super init];
    		[movieroles setDataSource:[[movies dataSource]
    			dataSourceQualifiedByKey:@"movieRoles"]];
    		return self;
    	}
    
The first line of this init method invokes any initialization performed by the object's superclass. Whenever you implement an init method, include a call to the super class's init method. If you omit the call to super, your objects won't be fully initialized.

The second line of this method assigns a new data source to the movieroles display group. A data source-an instance of an EODataSource subclass-is an object that defines a basic interface for providing enterprise objects. It exists primarily as a simple means for a WODisplayGroup or other higher-level class to access a store of objects. For example, when you tell a display group to fetch, it does so by telling its data source to fetch.

To restrict the objects that movieroles displays, you need to replace movieroles' data source with a detail data source. A detail data source is a data source that qualifies (restricts) its set of enterprise objects to an object that's selected in a master data source. A detail data source is set up to provide objects for the destination entity of a particular relationship.

The following expression:

[[movies dataSource] dataSourceQualifiedByKey:@"movieRoles"]
gets the data source from the movies display group and asks it to provide a detail data source. The data source returned by dataSourceQualifiedByKey: is set up to provide MovieRole objects that are related to one of movies' enterprise objects through the movieRoles relationship.

Qualify the detail data source

In a master-detail setup, changes to the detail apply to the objects in the master; for example, adding an object to the detail also adds it to the relationship of the master object. Once you have a detail data source, you can set the master object by sending the detail a qualifyWithRelationshipKey:ofObject: message. The detail then uses the master object in evaluating the relationship and applies inserts and deletes to that master object. In the MovieDetails page, this plays out as follows: If you insert a new MovieRole object in the movieroles display group, it is also added to the movieRoles array of the selected Movie object.

  1. Modify the setMovie: method to look like this:
    	- setMovie:aMovie {
    		if (aMovie)
    			[movies setObjectArray:[NSArray
    arrayWithObject:aMovie]];
    else [movies setObjectArray:nil]; [movies selectObject:aMovie]; // Add the following lines. [[movieroles dataSource] qualifyWithRelationshipKey:@"movieRoles" ofObject:aMovie]; [movieroles fetch]; }

Create the repetition bindings

  1. Bind the movieroles displayedObjects method to the repetition's list attribute.

    WebObjects Builder adds the movieRole variable back and automatically binds it to the repetition's item attribute.

    movieRole's displayedObjects method returns an array of roles in the selected movie. In general, WODisplayGroup's displayedObjects method returns the list of objects that you want to display.

    Typically, a display group's object array contains more objects than the display group makes available for display. Most display groups fetch all of the objects in the database, and you usually do not want to display all of the objects in the database. To display fewer objects, you associate a qualifier with the display group. After the display group has performed the fetch, it applies the qualifier to the fetched objects. displayedObjects returns an array that either contains the entire array of objects after the qualifier has been applied, or if the batch size is greater than 0, it returns the objects in the current batch.

    For example, suppose there are one thousand records in the database. A typical display group would fetch all one thousand records. Then suppose the display group had a qualifier that narrows the list down to one hundred objects that should eventually be displayed. If the batch size is 0 (indicating that the display is not being batched), displayedObjects returns all one hundred objects that should be displayed. If the batch size is ten, displayedObjects returns the ten objects out of those one hundred that currently should be displayed. When the page is loaded, displayedObjects returns the first ten objects. When the Next Page button is clicked, displayedObjects returns the next ten objects, and so on.

  2. Bind movieRole talent firstName to the first string element.

  3. Bind movieRole talent lastName to the second string element.

  4. Bind movieRole roleName to the last string element.

Table of Contents Next Section