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
* angularjs 1.2.2 - http://code.angularjs.org/1.2.2/angular-1.2.2.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
Comments (1)
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)