Creating Updating Content Edit Widgets

Brightspot comes with two standard updating widgets on the Content Edit Page: Publish Widget and URLs Widget. Both widgets have fields using traditional HTML form tags such as <input>.

You can create custom updating widgets that provide web forms in the content edit page by extending UpdatingContentEditWidget—an abstract class that includes the abstract method displayOrUpdate you must override in addition to the abstract methods described in Creating. These widgets respond to events and instantiate custom objects for data validation and posting content to the database.

In the following example you create a widget for attributing an article to a reporter—a typical task in a ghost-writing scenario.

Step 1: Create Reporter Model

In this step, you create a simple Model to hold reporters’ first and last names.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package content.article;

import com.psddev.cms.db.Content;

public class Reporter extends Content {

    private String firstName;
    private String lastName;

    /* Getters and setters */

    public String getFullName() {
        return getFirstName() + " " + getLastName();
    }
}

In the previous snippet—

  • Line 5 declares the class Reporter that extends Content. In a more robust implementation, you might create the class Reporter that extends ToolUser, create the class ReporterRole that extends ToolRole, and then assign instances of Reporter to ReporterRole.
  • Lines 12–14 return a reporter’s full name as a concatenation of the reporter’s first and last name.

Step 2: Add Field to Model, Hide from Content Edit Form

By default, Brightspot places all of a Model’s fields in the Content Edit Form. In this example, you are attributing an article to a reporter, so a reporterCredit field must be part of the article’s Model. Because reporterCredit appears in an updating content edit widget, you must use the @ToolUi.Hidden annotation in the Model to remove the field from the content edit form.

public class Article extends Content implements Directory.Item {

   /* Other fields in an Article */

    @ToolUi.Hidden
    private Reporter reporterCredit;

    /* Getter and Setter */
}

Step 3: Declare a Custom Updating Content Edit Widget

package widgets;

import com.psddev.cms.tool.UpdatingContentEditWidget;

public class ReporterCreditWidget extends UpdatingContentEditWidget {

}

Brightspot instantiates this class every time an event occurs in the content edit page, such as when loading an item or clicking Publish.

Step 4: Display the Widget’s Header

You display the custom widget’s header by implementing the method getHeading in the class from Step 3.

public String getHeading(ToolPageContext page, Object content) {
    /* Return string appearing in widget's title bar. */
}

Step 5: Display the Widget’s Body

You display the custom widget’s body, including form elements, by implementing the method displayOrUpdate in the class from Step 3.

public void displayOrUpdate(ToolPageContext page, Object content, ContentEditWidgetPlacement placement) throws IOException {
    /* Use page.write methods to display the widget's body,
       including form elements. */
}

Step 6: Catch the Update Event

The parameter placement in Step 5 is passed as null when the widget detects an update event. You test for null to process the widget’s current state.

Warning

Writing HTML to the content edit page when (placement == null) may corrupt the content state. Do not write HTML in this code block.

if (placement == null) {
    /* Retrieve form values and update database. */
}

Step 7: Position the Custom Updating Widget

You provide a position for the custom updating widget in the content edit page by implementing the method getPlacement in the class from Step 3.

public ContentEditWidgetPlacement getPlacement(ToolPageContext page, Object content) {
    /* Return one of the placement constants. */
}

See the table Placement Constants for a list of possible placement values.

Step 8: Set Condition for Displaying Content Edit Widget

Custom updating content edit widgets often appear in the UI for certain types of content and are suppressed for other types. You override the method shouldDisplay with a condition that evaluates to true when you want the content edit widget to appear.

public boolean shouldDisplay(ToolPageContext page, Object content) {
     /* Condition for displaying custom updating widget. */
 }

Step 9: Display Custom Updating Widget in Content Edit Page

The following snippet shows an entire class for displaying the custom updating widget Reporter Credit in the content edit page. The widget lists the available reporters which can be assigned to the current article. When the user clicks Publish, Brightspot updates the article’s record with the selected reporter. This example assumes you have a Model that includes a field reporterCredit with the associated getter and setter as descried in Step 2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package widgets;

import com.psddev.cms.tool.ContentEditWidgetPlacement;
import com.psddev.cms.tool.ToolPageContext;
import com.psddev.cms.tool.UpdatingContentEditWidget;
import com.psddev.dari.db.Query;
import content.article.*;

import java.io.IOException;
import java.util.List;
import java.util.UUID;

public class ReporterCreditWidget extends UpdatingContentEditWidget {

    @Override
    public void displayOrUpdate(ToolPageContext page, Object content, ContentEditWidgetPlacement placement) throws IOException {

        Article myArticle = (Article) content;

        if (placement == null) {
            UUID reporterID = page.param(UUID.class, "reporter.select");
            Reporter creditedReporter = Query.from(Reporter.class).where("id = ?", reporterID).first();
            myArticle.setReporterCredit(creditedReporter);
            return;
        }

        List<Reporter> reporters = Query.from(Reporter.class).selectAll();
        Reporter currentReporter = myArticle.getReporterCredit();

        page.writeStart("select", "name", "reporter.select");
            page.writeStart("option", "value", "").writeEnd(); /* Initial blank option */
            for (Reporter reporter : reporters) {
                page.writeStart("option", "selected", reporter.equals(currentReporter) ? "selected" : null, "value", reporter.getId());
                    page.writeHtml(reporter.getFullName());
                page.writeEnd(); /* option */
            }
        page.writeEnd(); /* select */
    }

    @Override
    public ContentEditWidgetPlacement getPlacement(ToolPageContext page, Object content) {
        return ContentEditWidgetPlacement.RIGHT;
    }

    @Override
    public String getHeading(ToolPageContext page, Object content) {
        return "Reporter Credit";
    }

    @Override
    public boolean shouldDisplay(ToolPageContext page, Object content) {
        return content instanceof Article;
    }
}

In the previous snippet—

  • Line 13 declares the class ReporterCreditWidget.
  • Line 18 casts the incoming object as an Article.
  • Lines 20–25 trap the widget’s update event.
    • Line 21 retrieves the selected reporter’s UUID.
    • Line 22 retrieves the Reporter record matching the selected reporter’s UUID.
    • Line 23 assigns the retrieved reporter record to the article.
  • Line 27 retrieves all of the reporters.
  • Line 28 retrieves the current article’s reporter credit.
  • Lines 30–37 render the widget’s body with an HTML <select> field. The field’s options are a default blank entry and the list of retrieved reporters.
  • Lines 40–43 position the widget in the right rail.
  • Lines 45–48 display the widget’s heading Reporter Credit.
  • Lines 50–53 display the widget if the current content type is an article.

Based on the previous snippet, the custom updating content widget Reporter Credit appears in the right rail of the content edit page.

../../../_images/updating-content-edit-widget.png

See also: