Search code examples
angularjs-scopejhipster

AngularJS displaying a list of objects from rest endpoint?


I have a Hipster application that I want to use to display a list of words on a page generated by user input. Ex: A user enters the string 'ba' and the application generates a list of all words that are in a local data structure that begin with 'ba'. What I'm trying to figure out is how to pass the string back to the server and return a list. Is that what the $scope variable is for? I think what I'm trying to figure out is how to implement 2-way data binding...

RestController:

@RestController
@RequestMapping("/api")
public class WordResource {

private final Logger log = LoggerFactory.getLogger(WordResource.class);

@Inject
private TreeService treeService;

/**
 * GET  /words : get all the words.
 *
 * @return the ResponseEntity with status 200 (OK) and the list of words in body
 */
@RequestMapping(value = "/words",
    method = RequestMethod.GET,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<Word> getAllWords() {
    log.debug("REST request to get all Words");
    return treeService.getAllWords();
}

/**
 * GET  /words : get all the words.
 *
 * @return the ResponseEntity with status 200 (OK) and the list of words in body
 */
@RequestMapping(value = "/ten-words",
    method = RequestMethod.GET,
    produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<Word> getSubWords(@PathVariable String word) {
    log.debug("REST request to get all Words");
    return treeService.getTenWordsFrom(word);

}
}

HTML

<div ng-cloak>
<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8"/>
    <!--/*@thymesVar id="pageTitle" type=""*/-->
    <title th:text="${pageTitle}">title placeholder</title>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>

    <link rel="stylesheet" href="https://bootswatch.com/superhero/bootstrap.min.css"/>

    <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>

</head>

<body>

<form>
    <div class="form-group">
        <input type="text" name="searchStr" class="form-control" placeholder="Search Words..."/>
    </div>
</form>


<div class="row well">
    <div class="col-md-4">

        <!--word list goes here-->

    </div>
</div>

</body>
</html>

</div>

Controller:

(function() {
'use strict';

angular
    .module('treeWordsApp')
    .controller('HomeController', HomeController);

HomeController.$inject = ['$scope', 'Principal', 'LoginService', '$state'];

function HomeController ($scope, Principal, LoginService, $state) {
    var vm = this;

    vm.account = null;
    vm.isAuthenticated = null;
    vm.login = LoginService.open;
    vm.register = register;

    $scope ({


    });

}
})();

Solution

  • I believe you mixed the concepts a little bit. The $scope is used to create 2-way databinding at the client level, which means that everything that changes locally in the client, is updated on the UI and vice-versa.

    Before creating the local bind, your client (HomeController) has to get the data from somewhere, in your case, the "WordResource" service. To do that, you can use the AngularJS "$http" service: https://docs.angularjs.org/api/ng/service/$http

    The $http service will call your Java service, and get all the data that you need back to the controller. What is left to do on the client side, is to create a variable in the local $scope to hold the list of words, let's cal it "wordList":

    $scope.wordList = [];
    

    And then create the two way bind in the interface, by using, for example, "ng-repeat": https://docs.angularjs.org/api/ng/directive/ngRepeat

    ngRepeat will create an specified HTML element for each element in the list, for example:

    <div ng-repeat="word in wordList">
      <span>{{word}}</span>
    </div>
    

    ... will create a DIV with a child SPAN for each word in the list.

    This creates a 2-way bind, but what that means, is that any changes to the list in the $scope will be propagated to the UI, and any changes in the UI will be reflected in the $scope. If you want to change something in the server, you will need to add some extra logic to make an API call and update the resource, which goes beyond the scope of this question.

    In summary:

    1. Create a variable in the local $scope to hold the list of words
    2. Create the HTML binding in the UI
    3. Every time you want to update the list of words, make an API call using $http and populate $scope.wordList with the list of words that you got from the service

    Hope this helps.