Creating an Article ViewModel

In the MVVM pattern, a ViewModel contains the logic for transforming the received Model’s data into a View. In this lesson, you declare an article ViewModel to transform data required by the article’s View.

Step 1: Adding the Article’s ViewModel

In this step, you create the article’s ViewModel. This ViewModel retrieves the headline, body, and image from the Model’s instance, and then injects them into the corresponding Handlebars placeholders.

  1. Returning to IDE, in the same directory as Article.java, create a new file ArticleViewModel.java and enter the following text:
 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
package brightspot.tutorial.article;

import brightspot.tutorial.image.Image;

import com.psddev.cms.rte.RichTextViewBuilder;
import com.psddev.cms.view.ViewInterface;
import com.psddev.cms.view.ViewModel;
import com.psddev.dari.util.StorageItem;
import com.psddev.handlebars.HandlebarsTemplate;

@ViewInterface
@HandlebarsTemplate("brightspot/tutorial/article/Article")
public class ArticleViewModel extends ViewModel<Article> {

    public String getHeadline() {
        return model.getHeadline();
    }

    public String getLeadImageUrl() {
        Image leadImage = model.getLeadImage();
        if (leadImage != null) {
            StorageItem file = leadImage.getFile();
            if (file != null) {
                return file.getPublicUrl();
            }
        }
        return null;
    }

    public CharSequence getBody() {
        String body = model.getBody();
        if (body != null) {
            return RichTextViewBuilder.buildHtml(body, (rte) -> null);
        }
        return null;
    }
}

In the previous snippet—

  • Lines 11 declares this class to fulfill the contract between the ViewModel and a Handlebars template.
  • Lines 12 specifies the Handlebars template with which this ViewModel interacts. This is the same Handlebars template you created in Step 1: Adding the Article’s View (without the .hbs extension).
  • Line 13 specifies that this ViewModel applies to Models of type Article. In particular, the ViewModel can call methods defined within Article.
  • Lines 15–17 retrieve headline text from the Model as a string, placing the string inside the {{headline}} placeholder within the Handlebars file.
  • Lines 19–28 retrieve the image’s URL from the Model as a string, placing the string inside the {{leadImageUrl}} placeholder within the Handlebars file.
  • Lines 30–36 retrieve the body rich text from the Model as a string, replacing the escaped HTML tags with unescaped HTML tags. The ViewModel places this string inside the {{body}} placeholder within the Handlebars file.

Step 2: Adding the Page’s ViewModel

In this step you create the nested ViewModel that prepares the article’s display.

  1. Returning to the IDE, create the file PageViewModel.java in the directory src/main/java/brightspot/tutorial/page/, and enter the following text:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package brightspot.tutorial.page;

import com.psddev.cms.db.Seo;
import com.psddev.cms.view.ViewInterface;
import com.psddev.cms.view.ViewModel;
import com.psddev.cms.view.PageEntryView;
import com.psddev.handlebars.HandlebarsTemplate;

import brightspot.tutorial.article.Article;
import brightspot.tutorial.article.ArticleViewModel;

@ViewInterface
@HandlebarsTemplate("brightspot/tutorial/page/Page")
public class PageViewModel extends ViewModel<Article> implements PageEntryView {

    public String getTitle() {
        return model.as(Seo.ObjectModification.class).findTitle();
    }

    public ArticleViewModel getBody() {
        return createView(ArticleViewModel.class, model);
    }
}

In the previous snippet—

  • Line 12 declares this class to fulfill the contract between the ViewModel and a Handlebars template.
  • Line 13 specifies the Handlebars template with which this ViewModel interacts. This is the same Handlebars template you created in Step 2: Adding the Page’s View (without the .hbs extension).
  • Lines 16–18 search through the Model’s fields that can serve as a title, returning as a string the first one that is populated. The ViewModel places the string inside the {{title}} placeholder within the Handlebars file.
  • Lines 20–22 create a nested View using the article’s ViewModel you created in Step 1 and the current Model instance. The ViewModel places the resulting nested View inside the {{body}} placeholder within the Handlebars file.

Step 3: Displaying the Resulting View

  1. Refresh the web page running at localhost:9480. The Publish widget in the content edit form now has a Preview control. This control appears because Brightspot detected the availability of a ViewModel for the article’s Model.

    ../../../_images/preview-control-in-publish-widget.svg
  2. In the Publish widget, click Preview. The Preview Pane appears.

    ../../../_images/preview-pane.png

Summary

In this lesson you learned the following skills:

  • How to create a ViewModel that retrieves information from a Model to populate a Handlebars template.
  • How to create a nested View from within a ViewModel.