-
Notifications
You must be signed in to change notification settings - Fork 28
Recipe Customize 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.
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.
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.
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!)
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.
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.
- The
DetailCtrl
is being created. - 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
.
- We set up
ctrl
as the name for the scope (aka the stored information or state) available in the template, as we saw above. - 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
andctrl.json
. The logic depends on the incoming content-type of the data. - The document content and its MarkLogic uri are made available to the template through
ctrl.doc
andctrl.uri
.
TODO: perhaps calculate a pro-rated withdrawal penalty for anyone who has not maintained a balance for at least 5 years
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
Understanding this library
- Background
- Explaining the stack
- Project folder structure
- Core Tools and Components
- REST extensions
- UI and UX Details
- Possible Issues
Creating your own demo