AngularJS-Twig conflict with double curly braces - angularjs

As you know, both angular and twig has common control construction - double curly braces. How can I change default value of Angular?
I know that I can do it in Twig, but in some projects I can't, only JS.

You can change the start and end interpolation tags using interpolateProvider service. One convenient place for this is at the module initialization time.
angular.module('myApp', []).config(function($interpolateProvider){
$interpolateProvider.startSymbol('{[{').endSymbol('}]}');
});
https://docs.angularjs.org/api/ng/provider/$interpolateProvider

This question appears answered, but a more elegant solution that hasn't been mentioned is to simply enclose the curly braces in quote marks between the twig curly braces, like so:
{{ '{{myModelName}}' }}
If you are using a variable for the contents, do this instead:
{{ '{{' ~ yourvariable ~ '}}' }}
You should use single quotes, not double quotes. Double quotes enable string interpolation by Twig so you have to be more careful with the contents, especially if you are using expressions.
If you still hate seeing all those curly braces, you can also create a simple macro to automate the process:
{% macro curly(contents) %}
{{ '{{' ~ contents ~ '}}' }}
{% endmacro %}
Save it as a file and import it into your template. I am using ng for the name because it is short and sweet.
{% import "forms.html" as ng %}
Or you can put the macro at the top of your template and import it as _self (see here):
{% import _self as ng %}
Then use it as follows:
{{ ng.curly('myModelName') }}
This outputs:
{{myModelName}}
...and a follow up for those that use MtHaml alongside Twig. MtHaml enables the use of AngularJS curlies in the normal manner because any Twig code is accessed though - and = instead of {{ }}. For example:
Plain HTML + AngularJS:
<tr ng-repeat="product in products">
<td> {{ product.name }} </td>
</tr>
MtHaml + AngularJS:
%tr(ng-repeat="product in products")
%td {{ product.name }}
MtHaml + AngularJS with MtHaml-style Twig:
- set twigVariable = "somevalue"
= twigVariable
%tr(ng-repeat="product in products")
%td {{ product.name }}

As mentioned in similar question about Django and AngularJS, trick with changing default symbols (in Twig or AngularJS) can provide incompatibility with third-party software, which will use these symbols.
So best advice I found in google: https://groups.google.com/d/msg/symfony2/kyebufz4M00/8VhF1KWsSAEJ
TwigBundle does not provide a configuration for the lexer delimiters
as changing them would forbid you to use any templates provided by
shared bundles (including the exception templates provided by
TwigBundle itself).
However, you could use the raw tag around your angular templates to
avoid the pain of escaping all curly braces:
http://twig.sensiolabs.org/doc/tags/raw.html
-- Christophe | Stof
Tag was renamed to verbatim

You can use too the attribute-based directive <p ng-bind="yourText"></p> is the same as <p>{{yourText}}</p>

You can use \{{product.name}} to get the expression ignored by Handlebars and used by Angular instead.

This is a compiled version of the best answers and a example for verbatim blocks:
For single insertions, use:
{{ '{{model}}' }}
or if you use a twig variable
{{ '{{' ~ twigVariableWitModelName ~ '}}' }}
Verbatim, is very elegant and readable for several angular variables:
<table ng-table>
{% verbatim %}
<tr ng-repeat="user in $data">
<td data-title="'Name'">{{user.name}}</td>
<td data-title="'Age'">{{user.age}}</td>
</tr>
{% endverbatim %}
</table>

If you're not interested in changing the template tags of the existing angular syntax which would require some confusing rewriting of your existing angular templates.
One can just use the twig template tags with angular tags like so:
{% verbatim %}{{yourName}}{% endverbatim %}
Found this on another similar thread answer: Angularjs on a symfony2 application

Alternatively you can change the characters used by Twig. This is controlled by the Twig_Lexer.
$twig = new Twig_Environment();
$lexer = new Twig_Lexer($twig, array(
'tag_comment' => array('[#', '#]'),
'tag_block' => array('[%', '%]'),
'tag_variable' => array('[[', ']]'),
'interpolation' => array('#[', ']'),
));
$twig->setLexer($lexer);

According to this post you should be able to do it like this :
angular.module('app', [])
.config(['$interpolateProvider', function ($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
}]);

I like #pabloRN, but I would prefer to use span instead of p, because for me p will add line to the result.
I will use this:
<span ng-bind="yourName"></span>
I also use aText with the cursor inside the double quote so I don't have to rewrite the whole thing over and over again.

You can create a function in twig to surround your angular directives, so like instead of going ...
{{"angular"}}
you go ...
{{angular_parser("angular stuff here output curlies around it")}}

Related

AngularJS to display one section in Italic

Hi i'm creating a Harvard Reference Generator using AngularJS ive got it working perfectly, i can get it to create the full reference however i need one section to be styled in italics, the information is captured using a form. I require a little help with the output.
Current Output Code:
{{
book_author+" "+book_multiple_authors+" ("+book_year+").
"+book_title+".
"+book_place+":
"+book_publisher+".
"+ book_edition
}}.
What i need is for one section "book_title" to be shown in italics
I have tried:
{{
book_author+" "+book_multiple_authors+" ("+book_year+").
<i>"+book_title+".</i>
"+book_place+":
"+book_publisher+".
"+ book_edition
}}.
{{
book_author+" "+book_multiple_authors+" ("+book_year+").
"+<i>book_title</i>+".
"+book_place+":
"+book_publisher+".
"+ book_edition
}}.
{{
book_author+" "+book_multiple_authors+" ("+book_year+").
"<i>+book_title+</i>".
"+book_place+":
"+book_publisher+".
"+ book_edition
}}.
Nothing seems to work, i cant find any further reference to formatting the angularjs output specific to one section. What am i missing, any help would be greatly appreciated. That You.
To have HTML rendered within ng expressions, you need to use ngSanitize or $sce dependency. Else, HTML will be rendered as string inside your expressions.
In your case, you can simplify it by breaking it down to multiple elements:
<span ng-bind="book_author"></span>
<span ng-bind="book_multiple_authors"></span>
<span ng-bind="book_year"></span>
<i>
<span ng-bind="book_title"></span>
</i>
<span ng-bind="book_place"></span>
<span ng-bind="book_publisher"></span>
<span ng-bind="book_edition"></span>
Code between double curly braces in AngularJS is meant to be JavaScript, so it can't contain HTML tags. The way around it would be along these lines:
{{book_author+" "+book_multiple_authors
+" ("+book_year+").&nbsp";}}
<i>{{book_title}}</i>
{{" "+book_place+": "+book_publisher
+". "+book_edition;}}
Let me know if this works for you, if not we can try CSS instead to render text in italics.
Best wishes,
Lukasz

AngularJs - Pass angular argument to file twig

How can I pass an Angular item to twig file included?
This is my twig file that I want to include:
<a href="javascript:void(0)" title="[{ hostess.gender == 'F' ? 'Hostess top' : 'Steward top' }]">
<img src="{{ WBASE }}/assets/img/badge/top-profile.png" class="c-badge [{ extraClass }]"/>
</a>
Instead this is my twig file where I render data through angular loop. I need to include a twig file if the condition is true:
{% if hostess.top %}
{% include '_commons/elements/ng-badge-top.twig' with {'hostess': hostess} %}
{% endif %}
But it doesn't work. How can I do it?
I think that you won't be able to do it like that.
Take in consideration that angular is front-side rendered and twig server-side.
If you want to achive that, you will probably have to craete your ng-badge-top.twig as a html and include it with angular using "ng-include".
You can also try something like this:
<div ng-if="[{ hostess.top }]"
ng-include="'{{ path('view_route', { view: 'Content/test.html.twig' }) }}'"></div>
This last piece of code will do a call to the server to get a html file and render it. Take in consideration that this controller should serve HTML files, otherwise angular won't be able to process them. Didn't tested it, but if it doesn't work tell me and we will figure out what's wrong.
If those solutions doesn't fit your needs I can give you other options :)

How to get Angular.js binding tags safely past Python's Jinja2?

Python's server-side Jinja2 and JavaScript's client-side Angular should both be able to run on the same application but it's sort of troublesome when i.e.
<h1 class="object-attribute" ng-model="object" >{{ object.attribute }}</h1>
has to "make it past the Python" first without hiccups. How would one best disambiguate the Jinja2 from the Angular?
I know that I can nest the Angular within Jinja2's {% raw %}{% endraw %} tags as far as the server goes, but what way could I solve this on the client-side?
As documented in the Angular Documentation, you can change the symbols used for expressions.
This feature is sometimes used to mix different markup languages, e.g. to wrap an Angular template within a Python Jinja template (or any other template language). Mixing templating languages is very dangerous. The embedding template language will not safely escape Angular expressions, so any user-controlled values in the template will cause Cross Site Scripting (XSS) security bugs!
var customInterpolationApp = angular.module('customInterpolationApp', []);
customInterpolationApp.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('//');
$interpolateProvider.endSymbol('//');
});
customInterpolationApp.controller('DemoController', function() {
this.label = "This binding is brought you by // interpolation symbols.";
<div ng-app="customInterpolationApp" ng-controller="DemoController as demo">
//demo.label//
</div>

How do I escape curly braces for display on page when using AngularJS?

I want the user to see double curly braces, but Angular binds them automatically. This is the opposite case of this question where they want to not see curly braces used for binding when the page is loading.
I want the user to see this:
My name is {{person.name}}.
But Angular replaces {{person.name}} with the value. I thought this might work, but angular still replaces it with the value:
{{person.name}}
Plunker: http://plnkr.co/edit/XBJjr6uR1rMAg3Ng7DiJ
<code ng-non-bindable>{{person.name}}</code>
Documentation # ngNonBindable
Edit: adding \ slash between brackets inside the quotes works
{{ "{{ person.name }\}" }}
this too .. by passes angular interpreting
{{ person.name }<!---->}
this too ..
{{ person.name }<x>}
{{ person.name }<!>}
In our case we wanted to present curly brackets in a placeholder, so they needed to appear inside an HTML attribute. We used this:
<input placeholder="{{ 'Hello {' + '{person.name}' + '}!' }}" ...>
As you can see, we are building up a string from three smaller strings, in order to keep the curly braces separated.
'Hello {' + '{person.name}' + '}!'
This avoids using ng-non-bindable so we can continue to use ng- attributes elsewhere on the element.
Updated for Angular 9
Use ngNonBindable to escape interpolation binding.
<div ngNonBindable>
My name is {{person.name}}
</div>
Use ng-non-bindable in container, this is effective on all element inside here container.
<div ng-non-bindable>
<span>{{person.name}}</span>
<img src="#" alt="{{person.name}}">
<input placeholder="{{person.name}}">
</div>
<span>{{</span>{{variable.name}}<span>}}</span>
I wanted single brackets across text and the above solutions didn't work for me. So did want the Angular recommended.
Angular Version: 5
Required Text: My name is {person.name}.
<span>My name is {{'{'}}person.name{{'}'}}.</span>
I hope it helps someone.
From Angular compiler:
Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.)
So in the original question - you would end up with:
My name is {{ '{' }}{{ '{' }}person.name{{ '}' }}{{ '}' }}

jinja2 form render does not allow attribute which contains "-"

I am trying to customize the form template base on this tutorial. As I understand, render() just add some attributes to the tag. For example, I add placeholder = "abc" and it works well.
{% call inserttourbus(id = "formAddNewRow" ) %}
<div class="fieldWrapper">
{% if inserttourbus['bustype'].label() %}Bus Type{% endif %}
{{ inserttourbus['bustype'].render(placeholder="abc")|safe }}
{% if inserttourbus['bustype'].errors() %}Not filled yet!{% endif %}
</div>
{% endcall %}
Here is my problem:
- I use bootstrap typeahead for my template so I need to add the following attribute to the inserttourbus textbox
data-provide="typeahead" data-items="4" data-source='["Alabama","Alaska"]'
So it will become
{{ inserttourbus['bustype'].render(placeholder="abc", data-provide="typeahead", data-items="4", data-source='["Alabama","Alaska"]')|safe }}
But the jinja2 engine seems does not accept data-provide, data-items, so on because it contain "-" character. If I changed data-provide to dataprovide, the jinja2 engine can render the code well.
However, in bootstrap typeahead javascript, all variables are defined as data-provide, data-items. If I change them to dataprovide, dataitems, the javascipt stop working.
Please give me a solution:
- How to make jinja2 accept attribute which has "-"
- Other solutions, advices
Check out this snippet for doing this in Flask. I imagine it would work the same way for Django; pass HTML attributes with invalid Jinja2 (Python) syntax inside an ad-hoc dictionary:
{{ inserttourbus['bustype'].render(placeholder="abc",
**{'data-provide':'typeahead',
'data-items':'4',
'data-source':'["Alabama","Alaska"]'}) }}
A Hyphen is used as the subtraction operator in Python. So do not use it in names. You can use it ofcourse in strings.

Resources