Home » Angularjs » Mixing Spring MVC with Angular.JS

Mixing Spring MVC with Angular.JS

Posted by: admin November 29, 2017 Leave a comment

Questions:

I want to make a Single Page Application with my Spring MVC Backend.
I’ve just learnt Angular.js.

I have a left menu consisting of two links.

One makes request to the below controller. This controller makes url forwarding and lists details of something which is filled by the given model attributes.

@RequestMapping(value = "{id}/rev/{rid}/detail", method = RequestMethod.GET)
public String detail(@PathVariable("id") Project project, @PathVariable("rid") Rev rev, Model model, HttpSession session) {
        User user = ((User) session.getAttribute(CSession.USER));
        model.addAttribute("project", project);
        model.addAttribute("rev", rev);
        model.addAttribute("cont", revContBS.getRevCont(rev, user));

        return "template/detail";
}

The other makes an ajax call to the controller which returns JSON.

@RequestMapping(value = "file/{fid}", method = RequestMethod.GET)
public @ResponseBody String getFile(@PathVariable("fid") FV fv) {
        return repBS.getVerCon(fv);
}

Currently, I have a decoration: the header, the left menu, and the main content area.
If I click the first link, it will make a full page refresh (because it makes page forwarding and jsp templating)
If I click the second link, it will only change the main content area.

I want to change the behavior of the first link because it should change only the content area.
Is it possible with Angular.JS + Spring MVC?
I mean, I will a request a page from the spring mvc. It will template “template/detail.jsp” with given model attributes. But I will put this page into the content area of my ng-app.

Currently, I have problems in following areas:

  1. @RequestMapping(value = “{id}/rev/{rid}/detail”, method = RequestMethod.GET) is parametric. I couldn’t find a way to make route forwarding parametric.
  2. I don’t know how I should re-serve my “template/detail.jsp” so that it will be placed into the div called ng-view.
Answers:

The directive ng-view of AngularJS is used to render a template associated to the current route into your html page.
The main point is that your templates should be managed client side only.

What you try to do here is to render a template server side, using Spring MVC but this is not the idea of a single page application with AngularJS.

Instead, your spring mvc controllers should only return json object : you write RESTful services and use AngularJS to render your template and fetch your model.

Here is a complete example for your use case :

index.html :

<html ng-app="myApp">
<head>
</head>
<body>
    <!-- Your menu -->
    <ul>
        <li><a href="#/project/1/rev/1">Project 1 - Rev 1</a></li>
        <li><a href="#/project/1/rev/2">Project 1 - Rev 2</a></li>
    </ul>

    <!-- Your content -->
    <div ng-view>
    </div>
</body>
</html>

Your template (“template/detail.html”)

<div>Id of project : {{project.id}}</div>

Your angular application :

angular.module('myApp', []).
    config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            // Bind your route with your template and associated controller
            // Your template will be loaded into ng-view area
            when('/project/:projectId/rev/:revId', { templateUrl: 'template/detail.html', controller: MyController }).

            // Default route
            otherwise({redirectTo: '/'});
    }]);

function MyController($scope, $routeParams, $http) {
    // Use $routeParams to get parameter from your current route
    var projectId = $routeParams.projectId,
        revId = $routeParams.revId;

    // Here I use $http API from AngularJS but ng-resouce may be easier to use 
    // when you have to deal with rest resources
    $http.get('project/' + projectId + 'rev/' + revId).success(function(data) {
        $scope.project = data.project;
        $scope.rev = data.rev;
    });
}

Your Spring MVC controller with your REST service :

@RequestMapping(value = "{id}/rev/{rid}/detail", method = RequestMethod.GET)
@ResponseBody
public Map<String, Object> detail(
         @PathVariable("id") Project project,
         @PathVariable("rid") Rev rev,
         HttpSession session) {

    User user = ((User) session.getAttribute(CSession.USER));

    // I use a map for the example but you should probably use a "real" object
    // The idea here is that you return a rest resource
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("project", project);
    map.put("rev", rev);
    map.put("cont", revContBS.getRevCont(rev, user));
    return map;
}

Note that if you need a more complex router, you can have a look at AngularUI project.