Aziz Alfoudari
Aziz Alfoudari

Reputation: 5263

AngularJS - Passing values from backend to frontend

What's the best way to pass a value from the backend to AngularJS in the frontend? I'm using Django and the templates are able to spit out values that I need, however I'm not sure what's the best practice on passing these values to AngularJS.

Think of a blog post and its comments, If I had an AngularJS service that retrieves all the comments of a certain blog post by passing the post ID to the service, and Django is rendering the HTML template and it does know what's the post ID, however I need to pass this post ID to AngularJS and subsequently to the service.

One idea is to have it in a hidden <input> and assign this input to a model. Not very appealing.

Another one is to have a directive and pass this value in an attribute to this directive, this way I would be able to access this attribute's value:

// Django (or any backend) is rendering {{ object.value }}
<div class="myDirective" data-object-id={{ object.value }}>
   ...
</div>

angular.module('myDirectives', []).
    directive('myDirective', function() {
        return {
            restrict: 'C',
            transclude: false,
            link: function postLink($scope, $element, $attrs) {
                // $attrs.objectId would have the value
            }
        }
    });

These two approaches look fine. But I'm wondering if there is a cleaner way of doing this? Any approach that follows AngularJS best practices?

Upvotes: 29

Views: 29336

Answers (3)

Izhaki
Izhaki

Reputation: 23586

I believe the proper way to do this is for the server to render a script with a value provider, then dependency-inject it in your app. Like so:

index.php:

<html ng-app='myApp'>

<head>
    <title>AngularJS Back to Front</title>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js"></script>
    <script src='index.js'></script>
    <?php
        $globals = array(
            'count' => 1, 
            'title' => 'Active users',
            'users' => array(
                'name' => 'john',
                'age'  => 21
            )
        );

        $globalsJSON = json_encode( $globals )
    ?>

    <script>
        myApp.value('globals', <?=$globalsJSON;?>);
    </script>
</head>

<body ng-controller="myController">
    <div>{{title}}</div>
</body>

</html>

index.js:

var myApp = angular.module( 'myApp', [] );

myApp.controller( 'myController', [ 'globals', '$scope', function( globals, $scope ) {
    // Copy globals to scope
    for ( var property in globals ) {
        $scope[ property ] = globals[ property ];
    }
}]);

Upvotes: 9

pkozlowski.opensource
pkozlowski.opensource

Reputation: 117370

If you need to initialize only a handful of model values from a view the ng-init directive might be what you are looking for: http://docs.angularjs.org/api/ng.directive:ngInit

Using it you could simply write:

<div ng-init="myModel=backend-generated-value-here">
   ...
</div>

Having said the above you might have a bit of hard-time finding best practices for your use-case as AngularJS is focused on Web2.0, full-client-side web applications. At the moment it doesn't play ideally with the server-side generate content. It might change in the future versions of AngularJS.

Upvotes: 22

Tiago Rold&#227;o
Tiago Rold&#227;o

Reputation: 10649

If all you need is to setup initial values for a given "page" (meaning backend call to a view) then you can do as you demonstrated. I would only make it "cleaner" by setting up a global variable via javascript, like so:

// Django (or any backend) is rendering {{ object.value }}
<script>
  var backendVars = {
    {{object.name}} : {{object.value}}
    //and any other objects, manually parsed
  }
</script>

And read it on with angular on the bootstrapping process.

However, angularJS is a MVC of it's own, so you may want to be able to set/get data or backend controllers' processes, without necessarily reloading the entire page. The "cleanest" way is then to make a web service to return the data you need (i.e. a view that returns JSON, for instance) and retrieve it via $http or $resource service:

angular.module('myApp', []).
  controller('MainCtrl', function($scope, $html) {
    $html({
    method: 'GET',
    url: '/your/JSON/view.json'
      }).
      success(function(data, status){
        $scope.yourData = data;
      }).
      error(function(data, status){
        //whatever you need to do if the data is not available
      });
  }

Also, I should note that you shouldn't put data and logic directly on directives - they are meant for DOM manipulation - instead get your information on a controller, and then pass it on to a directive via scope inheritance, attributes or 2-way data binding. Hope it helps.

Upvotes: 9

Related Questions