Skip to content
This repository has been archived by the owner on Oct 5, 2020. It is now read-only.

Recipe Customize Detail Pages

Patrick McElwee edited this page Aug 12, 2016 · 4 revisions

Recipe: Customize the Detail Pages

This recipe is based on the sample data included with this slush-marklogic-node DEMO app template. Before beginning, be sure that you have following the Getting Started steps and loaded the sample data.

Starting Point

After you start your application from the command-line at the root of your source code with:

cd ~/slush-marklogic-node-tutorial # Or wherever your source code lives
gulp serve-local

navigate to http://localhost:3000/search and click on the first search result. It will look something like this:

Note that the default page allows you to view your data in both JSON and XML formats and also suggests similar documents (using MarkLogic's cts:similar-query in case you're curious).

Using this recipe, you will be able to make a more user-friendly detail page with HTML markup that pulls values out of the document. Hopefully, you will also learn concepts that will allow you to extend the ideas to whatever detail page you want to build in your own demos.

Step 1: Find the detail.html Template

The demo application generated by slush-marklogic-node on your computer has a ui directory. All the AngularJS front-end, client-side code resides in this directory. Learning about Angular will be helpful if you create your own demo apps using this generator, but no worries for now: We will provide enough Angular background to allow you to complete this recipe. The most important thing is to get a taste of the kinds of features that MarkLogic makes it easy to build.

Navigate into the ui/app directory, which houses all the Angular HTML templates and javascript files. Take a look around. You can see that sub-directories here group together particular pages or functions.

Navigate into ui/app/detail, where the detail-page template and javascript files live. In this recipe, we will only be editing files here.

Using your preferred text editor or IDE, open ui/app/detail/detail.html.

Note first that this file consists of a single overall <div> tag, with classes like row, detail, and col-sm-8. Those classes are defined by the Bootstrap 3 CSS library, which this demo app uses for styling.

If you are not used to Angular, the "HTML" tag in line 3 may surprise you:

<uib-tabset type="pills">

This is an Angular directive, a central feature of the Angular 1 library. Basically, directives allow you to write markup that looks like HTML, but which transforms the element in some way. This particular directive is defined by the AngularUI Bootstrap library (you can tell because of the uib-* prefix). It does what you might expect: creates the tabs that let you switch between JSON and XML views of your document.

Down lower, you can see the markup for the 'Similar' documents panel.

Let's leave the existing markup alone for now. It can be helpful to have a full view of the existing document as you design your page, so you can see which values are available to you. Before publishing your application to the public, you'll probably remove those raw JSON and XML views.

Step 2: Change the HTML Template

First, let's prove that we have the right file. Add some markup inside the second-level <div>, which defines the main column of the page, on a new line 3:

<h1>Hello World</h1>

Refresh the detail page and you should see your "Hello World" title at the top of the page. (By default, the gulp serve-local task that you ran watches for changes to your application files and reloads the browser using Browsersync, so it may have been refreshed for you!)

Step 3: Display Human-Readable Data from Your Document

If we look at our data, we see that there is a name field. That would make a much better title for the page.

But how do we get at the data?

It is being stored for us in the state of the Angular application. From the detail.html template, we can refer to it with the Javascript expression ctrl.doc.

Let's unpack that. For consistency, in all the generated templates, ctrl (short-hand for 'controller') refers to the stored state, or information, available to the template. Trust me for now. In the next step, we'll take a closer look at the controller that controls this state.

You can treat ctrl as a Javascript object with properties. In the detail.html context, one such property is doc, which has all the values of the current document.

So let's pull the person's name out of that data. Change your 'Hello World' title to the following:

<h1>{{ctrl.doc.name}}</h1>

Note the double curly-braces ({{}}). This is a signal to Angular, which processes the template, to evaluate the javascript inside. (This works for any arbitrary javascript, for example try putting in 1 + 1 and the title will be '2'.)

Now you have the trick and can pull out additional elements. For example, try:

<p>
  You are welcome to discover more about {{ctrl.doc.name}}!
  A person with eyes of {{ctrl.doc.eyeColor}},
    <span ng-if="ctrl.doc.gender === 'male'">his</span>
    <span ng-if="ctrl.doc.gender === 'female'">her</span>
  favorite fruit is {{ctrl.doc.favoriteFruit}}. And
    <span ng-if="ctrl.doc.gender === 'male'">he</span>
    <span ng-if="ctrl.doc.gender === 'female'">she</span>
  has a balance of {{ctrl.doc.balance}}.
</p>

Note the use of ng-if. There is a long list of similar Angular directives that can assist you in customizing your templates. (Don't try to learn them all at once!)

Try adding some more information to the page on your own.

Step 4: Find detail.controller.js

In the last example, we added a small amount of display-related logic into the view (to use gender-specific pronouns). But when you have more complicated logic, it is better not to try inserting that in a view template like this. Angular provides controllers for this purpose.

The relevant controller for our detail.html is conveniently saved in the same ui/app/detail directory. Use that handy text editor again to open up ui/app/detail/detail.controller.js.

Several things are happening here. For now, let's ignore the javascript and Angular boilerplate code and call out what work is being done.

  1. The DetailCtrl is being created.
  2. We inject the doc into the controller.
  • For the curious, the logic for getting the doc from MarkLogic actually lives in the detail route definition in ui/app/route/routes.js.
  • $stateParams is also injected. It is just an object holding the current URL parameters: in this case, the URI of the document stored in MarkLogic, which, you will notice, is part of the URL in your browser. It is something like /sample-data/data-0.json.
  1. We set up ctrl as the name for the scope (aka the stored information or state) available in the template, as we saw above.
  2. There is a good deal of logic that sets up the default JSON and XML views of the document content and makes tthose available to the template through ctrl.xml and ctrl.json. The logic depends on the incoming content-type of the data.
  3. The document content and its MarkLogic uri are made available to the template through ctrl.doc and ctrl.uri.

Step 5: Introduce Some Business Logic

TODO: perhaps calculate a pro-rated withdrawal penalty for anyone who has not maintained a balance for at least 5 years

Step 6: MarkLogic search

TODO: Do we want to go this far in this recipe? Could search for others who share a first or last name in common and include the count as a fun-fact