If you benefit from web2py hope you feel encouraged to pay it forward by contributing back to society in whatever form you choose!

web2py and angular.js - syntax collision with handlebars

There are several ways to overcome the syntax collision with handlebars:
1. Change web2py's delimiter syntax to something other than double-curly-braces.
2. Have custom web2py html-helpers
3. Change handlebars's delimiter syntax.
4a. Have separate files for the handlebars templates - ng-include.
4b. Have separate files for the handlebars templates - templateURL.
5. Avoid using expressions
 
The following examples use:
* web2py 2.7.4-stable+timestamp.2013.10.14.15.16.29 (LGPLv3 License) - http://www.web2py.com/examples/static/web2py_src.zip
 
 
 

1. Changing web2py's delimiter syntax

 
Here is an example using the response.delimiter to specify using something other than the default '{{'/'}}' in web2py:
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', []);
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    response.delimiters = ('<?', '?>')
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="<?=URL('static','angular-1.2.2/angular.js')?>"></script>
  <script src="<?=URL('static','controllers.js')?>"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <p>{{greeting.text}}, World</p>
  </div>
</body>
</html>
 
 
The html file script src attribute uses the web2py URL helper to get angular.js and controller.js:
  <script src="<?=URL('static','angular-1.2.2/angular.js')?>"></script>
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
 
Reference
* https://groups.google.com/forum/#!topic/web2py/-Oy7ssOl4bM
 

2. Using custom web2py html-helpers

 
Here is an example using a web2py html-helper to generate the correct syntax for handlebars delimiters.
 
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', []);
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
 
Edit applications/angular2py/models/db.py controller and add the following html-helper:
 
class HB(DIV):
    tag = ''
    def xml(self):
        return '{{%s}}' % super(HB, self).xml()
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="{{=URL('static','angular-1.2.2/angular.js')}}"></script>
  <script src="{{=URL('static','controllers.js')}}"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <p>{{=HB('greeting.text')}}, World</p>
  </div>
</body>
</html>
 
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
Reference
* https://groups.google.com/forum/#!topic/web2py/-CrviALMVy8
 
 
 

3. Change handlebars's delimiter syntax.

 
This example uses angular $interpolateProvider to set delimiters.
 
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', [], function($interpolateProvider) {
    $interpolateProvider.startSymbol('[[');
    $interpolateProvider.endSymbol(']]');
});
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="{{=URL('static','angular-1.2.2/angular.js')}}"></script>
  <script src="{{=URL('static','controllers.js')}}"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <p>[[greeting.text]], World</p>
  </div>
</body>
</html>
 
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
 
Reference:
* http://stackoverflow.com/questions/12923521/angular-js-custom-delimiter
 
 
 

4a. Have separate files for the handlebars templates - ng-include

 
Here is an example using angular ng-include to specify different handlebars template files.
 
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', []);
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="{{=URL('static','angular-1.2.2/angular.js')}}"></script>
  <script src="{{=URL('static','controllers.js')}}"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <div ng-include src="'../static/helloworldtemplate.html'"></div>
  </div>
</body>
</html>
 
 
Create the corresponding applications/angular2py/static/helloworldtemplate.html view file with the following:
 
<p>{{greeting.text}}, World</p>
 
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
 
Reference
* http://docs.angularjs.org/api/ng.directive:ngInclude
* http://stackoverflow.com/questions/13943471/angularjs-ng-include
 
 
 

4b. Have separate files for the handlebars templates - directives

 
Here is an example using angular with directives and templateURL to specify different handlebars template files.
 
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', []);
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
myApp.directive('helloworlddirective', function() {
  return {
    restrict: "E",
    replace: true,
    templateUrl: '../static/helloworldtemplate.html'
  };
});
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="{{=URL('static','angular-1.2.2/angular.js')}}"></script>
  <script src="{{=URL('static','controllers.js')}}"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <helloworlddirective></helloworlddirective> 
  </div>
</body>
</html>
 
 
Create the corresponding applications/angular2py/static/helloworldtemplate.html view file with the following:
 
<p>{{greeting.text}}, World</p>
 
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
 
Reference
* http://docs.angularjs.org/guide/directive
 
 

5. Avoid using Angular expressions

 
Here is an example using ng-bind instead of angular expressions ('{{'/'}}'):
 
Unzip and run web2py.py to start web2py/generate defaults; create the application angular2py.
 
Unzip the angular-1.2.2.zip to the following location:
 
angular-1.2.2.zip  ->  applications/angular2py/static/
 
 
Create applications/angular2py/static/controllers.js file with the following:
 
var myApp = angular.module('myApp', []);
 
myApp.controller('HelloController', function($scope) {
  $scope.greeting = { text: 'Hello' };
});
 
 
Edit applications/angular2py/controllers/default.py controller and add the following:
 
def helloworld():
    return dict()
 
 
Create the corresponding applications/angular2py/views/default/helloworld.html view file with the following:
 
<html ng-app="myApp">
<head>
  <script src="{{=URL('static','angular-1.2.2/angular.js')}}"></script>
  <script src="{{=URL('static','controllers.js')}}"></script>
</head>
<body>
  <div ng-controller='HelloController'>
    <p><span ng-bind="greeting.text"></span>, World</p>
  </div>
</body>
</html>
 
 
The ng-bind replaces the {{greeting.text}} expression:
    <p>{{greeting.text}}, World</p>
    <p><span ng-bind="greeting.text"></span>, World</p>
 
 
Making a request for the 'helloworld' page (http://127.0.0.1:8000/angular2py/default/helloworld) should deliver and run the angular.js app.
 
 
Reference
* http://docs.angularjs.org/guide/databinding
* http://docs.angularjs.org/guide/expression
 
-Rob Powell
 
 
 

 

Related slices

Comments (1)

  • Login to post



  • 0
    ramstein74 10 years ago

    I´m want to export a variable from my web2py controller to my controller.js and for example using your first suggestion and trying a ng-repeat with the array[1,2,3]

    in my web2py controller if i do

    x=[1,2,3]

    return dict(x=x)

     

    then in my controller.js i cannot access my x variable.

    $scope.cods= "<?=cods?>";

    i get this error

     

    Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: x in cods|filter:search, Duplicate key: string:?

    However if i embed my controller.js code in my web2py view it works

     

    Why?

    replies (1)
    • rppowell 10 years ago

      I am assuming that the controller.js is originally under /static/controllers.js.

      URLs to the static files do not get called through the framework and are simply returning the unprocessed file in the /static folder; thus, no value is substituted for the variable placeholder in the returned javascript for controller.js file request.

      When a request is made to the web2py framework via HTTP call (POST/GET), it is using a URL; the URL is processed and, after going through the application/controller path, is calling the specified controller's function. If there is a corresponding view, then the contents are used as a template to generate data that is returned.

      If the call is to 'static', then the URL file location is returned, no template processing of the file contents is done.

      See AngularJS-templates at https://groups.google.com/d/topic/angular2py-dev/7BInWrxk-ho/discussion with details at: https://groups.google.com/d/msg/angular2py-dev/7BInWrxk-ho/7IL2Ffij0psJ


Hosting graciously provided by:
Python Anywhere