Quantcast
Channel: Nuxeo Blogs » Product & Development
Viewing all articles
Browse latest Browse all 161

Creating a Thumbnail Browsing Module with AngularJS and the REST API – Part 2

$
0
0

Yesterday I explained how you could retrieve documents through a search and adapt them with business objects, all using the REST API. Today I’ll show you how I used that to create a nice infinite scrolling page using AngularJS.

Start by forking nuxeo-angular-sample on GitHub. It’s a simple application that allows you to browse, edit, delete or create documents in a Nuxeo instance. Follow the readme to have it running; it’s quick and easy.

Now if you haven’t already, browse into the yo folder. The first thing I did was to modify the app/scripts/app.coffee file (yes, the sample is written in CoffeeScript). I added a new call to the when method in the $routeProvider object.

"use strict"
angular.module("nuxeoAngularSampleApp", ['nxSession','ui.bootstrap','blueimp.fileupload'])
.value("nxUrl", "/nuxeo/api/v1" )
.factory("nxSession", ["nxSessionFactory","nxUrl",(nxSessionFactory,nxUrl)->
  nxSessionFactory(
    apiRootPath: nxUrl
  )
])
.config ($routeProvider) ->
  $routeProvider
  .when("/nav/*path/edit"
    templateUrl: "views/edit.html"
    controller: "EditCtrl"
  )
  .when("/nav/*path/new"
    templateUrl: "views/edit.html"
    controller: "CreateCtrl"
  )
  .when("/nav/*path"
    templateUrl: "views/main.html"
    controller: "MainCtrl"
  )
  .when("/slideshow/:tag"
    templateUrl: "views/slideshow.html"
    controller: "SlideshowCtrl"
  )

  .otherwise redirectTo: "/nav/"

This means that each time someone hits the http://localhost:9000/#/slideshow/anyTag URL, he sees the content of the app/views/slideshow.html template included in the index.html file. This view is automatically bound to the SlideshowCtrl controller. So I need to create the app/views/slideshow.html file and add a new SlideshowCtrl controller.

As you probably guessed already, the HTML file goes into the app/views sub-folder. I’ll start by a very simple file containing only an h2 tag. The double braces are how you insert objects from your controller inside a template.

<h2>{{searchTag}}</h2>

Hello World

If you go to http://localhost:9000/#/slideshow/anyTag, you will see {{searchTag}} and this is normal since we have not declared our controller yet. So to declare our controller, we will edit the app/scripts/controllers/main.coffee file. Just add this at the end:

.controller("SlideshowCtrl",
['$scope' ($scope) ->
  $scope.searchTag = 'hello world'
])

Now you should see a nice Hello World message on your page. It works because we’ve assigned the String value ‘hello world’ in the searchTag variable of our controller $scope object. As you can see we don’t need to instantiate the $scope. AngularJS injects it for us. Now what would be nice is to display the tag instead of the hello world message.

The when method call we added at the beginning was made on the $routeProvider object. Notice that all object from the AngularJS framework start with a ‘$’ char. We’re now going to inject this object just like we did for the scope.

.controller("SlideshowCtrl",
['$scope','$routeParams' ($scope,$routeParams) ->
  $scope.searchTag = $routeParams.tag
])

And as you can see it’s really easy to retrieve the tag segment of the URL. Now you should see something like this if you go to http://localhost:9000/#/slideshow/islands.
Tag Title

Remember that our goal is to display some documents resulting from a search. So we’re going to add a new service that will handle search. Let’s create a new file app/scripts/services/nxSearch.coffee to hold our search logic.

The code is pretty straightforward. Notice that we inject two AngularJS objects and one Nuxeo object: $http, $q and nxURL (see? no ‘$’ char there). nxURL does not come out of nowhere, it’s been defined in the app/scripts/app.coffee file.

angular.module('nuxeoAngularSampleApp')

.factory "nxSearch", ["$http","$q","nxUrl",($http,$q,nxUrl)->

  nxSearch = {}
  nxSearch.items = []
  nxSearch.busy = false
  nxSearch.isNextPageAvailable = true
  nxSearch.currentPageIndex = 0
  nxSearch.pageSize = 20
  nxSearch.query = undefined
  nxSearch.bo = undefined

  nxSearch.setBOAdapter = (bo)->
    nxSearch.bo = bo

  nxSearch.setPageSize = (pageSize)->
    nxSearch.pageSize = pageSize

  nxSearch.setQuery = (query)->
    nxSearch.query = query

  nxSearch.nextPage = ()->
    if !nxSearch.query?
      $q.reject("You need to set a query")
      return

    if !nxSearch.isNextPageAvailable
      return

    if nxSearch.busy
      return

    nxSearch.busy = true

    url = nxUrl + "/path/@search"
    if nxSearch.bo? then url += "/@bo/" + nxSearch.bo
    url += "?currentPageIndex="+nxSearch.currentPageIndex+"&pageSize="+nxSearch.pageSize+"&query=" + nxSearch.query;
    $http.get(url).then (response) ->
      docs = response.data
      if(angular.isArray(docs.entries))
        nxSearch.currentPageIndex = docs.currentPageIndex + 1
        nxSearch.isNextPageAvailable = docs.isNextPageAvailable
        nxSearch.items.push doc for doc in docs.entries
        nxSearch.busy = false
      else
        nxSearch.busy = false
        $q.reject("just because")

  nxSearch
]

This new CoffeeScript file will be automatically compiled to JavaScript by Grunt, but we still need to add the resulting JavaScript file to our code. Edit the index.html file to add this line at the end of the file:

    <script src="scripts/services/nxSearch.js"></script>

The next step is to use this code in our controller. Let’s start with something simple, like a list of documents:

    <ul>
      <li ng-repeat='item in items'>
        <span>{{item.title}}</span>
      </li>
    </ul>

Let’s modify our controller accordingly. I need to inject the nxSearch service and put an items variable in the scope.

.controller("SlideshowCtrl",
['$scope','$routeParams','nxSearch'
($scope,$routeParams,nxSearch) ->
  $scope.searchTag = $routeParams.tag
  # set our query
  nxSearch.setQuery("SELECT * FROM Document WHERE ecm:tag = '" +  $scope.searchTag + "'")
  # get the first result page
  nxSearch.nextPage()
  # expose our search items in the scope
  $scope.items = nxSearch.items
])

You should have something like this:

Document List

What about that infinite scroll I told you about? Because we only have the first page of results right now. Well it appears that there is an AngularJS module just for that. We’ll use Bower to install it. Simply type bower install nginfinitescroll --save while you’re in the yo directory. This will install the ngInfiniteScroll module and update the bower.json file where all the module dependencies are stored. We still have some work to do to enable that module. We need to add it to our module configuration in the app/scripts/app.coffee file.

angular.module("nuxeoAngularSampleApp", ['nxSession','ui.bootstrap','blueimp.fileupload','infinite-scroll'])

And we also need to include the JavaScript library at the end of our index.html file:

    <script src="scripts/services/nxSearch.js"></script>

Now we can start using the module. Go to your template and modify the <ul> tag like this:

<h2>{{searchTag}}</h2>

    <ul infinite-scroll='nextPage()' infinite-scroll-disabled='busy' infinite-scroll-distance='1'>
      <li ng-repeat='item in items'>
        <span>{{item.title}}</span>
      </li>
    </ul>
  <div ng-show='busy'>Loading data...</div>

</div>

This won’t work as is, we need to expose the busy variable and the nextPage method from our scope. Now we can modify our controller like this:

.controller("SlideshowCtrl",
['$scope','$routeParams','nxSearch'
($scope,$routeParams,nxSearch) ->
  $scope.searchTag = $routeParams.tag
  nxSearch.setQuery("SELECT * FROM Document WHERE ecm:tag = '" +  $scope.searchTag + "'")
  $scope.items = nxSearch.items
  # Expose the busy variable
  $scope.busy = nxSearch.busy
  # Expose the nextPage method
  $scope.nextPage = ()->
     nxSearch.nextPage()

])

And that’s it. You now have infinite scrolling of a document search. In the next part I’ll show you how to handle the Business Object adapter and show a nice thumbnail grid :-)

The post Creating a Thumbnail Browsing Module with AngularJS and the REST API – Part 2 appeared first on Nuxeo Blogs.


Viewing all articles
Browse latest Browse all 161

Latest Images

Trending Articles



Latest Images