Jinja2 to display image in browser - google-app-engine

mymodel.url is textproperty(string) which is something like this
<a href ='http://www.abc.com'><img src='http://xyz.com/></a><img src="http://www.abcdefd.com" />
In index.html, if I use {{mymodel.url}}, I will see the html code in my browser. In otherwords, jinja2 consider {{mymodel.url}} as string.
<a href ='http://www.abc.com'><img src='http://xyz.com/></a><img src="http://www.abcdefd.com" />
I want to see the image in my browser. How can I do it?

You have to indicate to jinja2 that this content is "safe" to display in a browser as HTML
{{mymodel.url|safe }}
HTML Escaping
When generating HTML from templates, there’s always a risk that a variable will include characters that affect the resulting HTML. There are two approaches: manually escaping each variable or automatically escaping everything by default.

Related

IFrame Not Being Rendered In ng-bind-html

I have a datasource that is used to render blog articles on a page. One of the entries contains an IFRAME. I see the IFRAME being returned in the datasource but it is never rendered to the page in the ng-bind-html.
This is my code:
<div class="blog-post-content" ng-bind-html="entry.content" itemprop="text">
</div>
If I switch this to the following, I see the IFRAME tag rendered out, but of course now it is RAW HTML.
<div class="blog-post-content" itemprop="text">
{{entry.content}}
</div>
How can I get this IFRAME to be rendered to the page.
The best approach here is to refactor your data source to only contain the URL, rather than the full iframe tag, and use <iframe ng-src="entry.content"></iframe>.
ng-bind-html isn't working for you because the sanitizer is protecting you from potential XSS attacks.
If you don't control the data source, but trust it completely, you can look into using e.g. scope.trustedContent = $sce.trustAsHtml(entry.content); in your directive, and <div ng-bind-html="trustedContent"></div> in the DOM.
(Not controlling it but trusting it completely is, of course, a contradiction in terms, so you may be better off parsing the data source inside your directive to extract the url, rather than trusting the entire string.)

Use of ng-src vs src

This tutorial demonstrates the use of the directive ngSrc instead of src :
<ul class="phones">
<li ng-repeat="phone in phones" class="thumbnail">
<img ng-src="{{phone.imageUrl}}">
</li>
</ul>
They ask to:
Replace the ng-src directive with a plain old src attribute.
Using tools such as Firebug, or Chrome's Web Inspector, or inspecting the
webserver access logs, confirm that the app is indeed making an
extraneous request to /app/%7B%7Bphone.imageUrl%7D%7D (or
/app/{{phone.imageUrl}}).
I did so and it gave me the correct result:
<li class="thumbnail ng-scope" ng-repeat="phone in phones">
<img src="img/phones/motorola-xoom.0.jpg">
</li>
Is there a reason why?
From Angular docs
The buggy way to write it:
<img src="http://www.gravatar.com/avatar/{{hash}}"/>
The correct way to write it:
<img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
Why? this is because on load of page, before angular bootstrapping and creation of controllers, browser will try to load image from http://www.gravatar.com/avatar/{{hash}} and it will fail. Then once angular is started, it understands that that {{hash}} has to be replaced with say logo.png, now src attribute changes to http://www.gravatar.com/avatar/logo.png and image correctly loads. Problem is that there are 2 requests going and first one failing.
TO solve this we should use ng-src which is an angular directive and angular will replace ng-src value into src attribute only after angular bootstrapping and controllers are fully loaded, and at that time {{hash}} would have already been replaced with correct scope value.
<img ng-src="{{phone.imageUrl}}">
This gives you expected result, because phone.imageUrl is evaluated and replaced by its value after angular is loaded.
<img src="{{phone.imageUrl}}">
But with this, the browser tries to load an image named {{phone.imageUrl}}, which results in a failed request.
You can check this in the console of your browser.
The src="{{phone.imageUrl}}" is unnecessary and creates an extra request by the browser. The browser will make at least 2 GET requests attempting to load that image:
before the expression is evaluated {{phone.imageUrl}}
after the expression is evaluated img/phones/motorola-xoom.0.jpg
You should always use ng-src directive when dealing with Angular expressions. <img ng-src="{{phone.imageUrl}}"> gives you the expected result of a single request.
On a side note, the same applies to ng-href so you don't get broken links till the first digest cycle kicks in.
Well actually it makes 100% sense because HTML gets processed sequentially and when this HTML page is being processed line by line, by the time it gets to this image, the line and processing the image, our phone.imageUrl is not yet defined yet.
And in fact, Angular JS has not yet processed this chunk of HTML, and hasn't yet looked for these placeholders and substitute these expressions with the values. So what ends up happening is that the browser gets this line and tries to fetch this image at this URL.
And of course this is a bogus URL, if it still has those mustache and curly braces in it, and therefore it gives you a 404, but once of course Angular takes care of this, it substitutes this URL for the proper one, and then we still see the image, but yet the 404 error message remains in our console.
So, how can we take care of this? Well, we can not take care of this using regular HTML tricks. But, we can take care of it using Angular. We need somehow to tell the browser not to try to fetch this URL but at the same time fetch it only when Angular is ready for interpretation of these placeholders.
Well, one way of doing it is to put an Angular attribute on here instead of the standard HTML one. And the Angular attribute is just ng-src. So if we say that now, go back, you'll see that there's no errors anymore because the image only got fetched once Angular got a hold of this HTML and translated all the expressions into their values.

Why is it that I see {{ ... }} before loading in AngularJS?

Do you know why is the {{ project.title }} before I see the real value of the scope.
And how to solve that ?
EDIT : <title>{{ pageTitle }}</title>
Page is loading
Page completely loaded
Your views for Angular.JS apps are just static HTML. If you remove the script tag that references Angular.JS, you'd end up with a page full of curly brackets in plain sight that never get replaced.
When your browser finished loading Angular.JS and loading your application, the expressions in those curly brackets are evaluated. That's why you see, for a brief moment, {{…}} in your page title.
As noted by others, the ng-cloak directive is usually the way to get rid of the flickering before the app is fully loaded.
But since ng-cloak is just CSS, it cannot be applied to the page title. You'll need ng-bind for that, as noted here.
<title ng-bind="pageTitle">Default Title</title>
You should be showing the code, but in general it's probably because you aren't using ng-cloak https://docs.angularjs.org/api/ng/directive/ngCloak
However, in the case of the title, you need to use ng-bind=project.title instead <title>{{ project.title }}</title>
Check How to hide {{title}} in <title> tag while using AngularJS?
To prevent this, you should use ng-bind instead of {{ }} for the first screen of your app.
ng-bind is a directive that is added to an element attribute, so it is displayed only when the page is loaded.
According to the description of ngBind, we usually use {{ expression }} to replace ng-bind. But in a first-loading situation, image that you firstly load AngularJS(maybe in index.html), it'll show the original {{ }}. After that, it transits to what u need. To overcome it, you can use ngCloak or just use ng-bind in your first page.
OK, please check this ?

Image not showing in angularjs, mobile

Image not showing in ng-repeat, getting all data from indexeddb and binding to page everything show up expect img in blackberry 10 webworks
<img data-ng-src='{{item.Picture}}' width="100px;" height="100px;"/>
{
id:48758,
Botanical_name:"Cladothamnus pyroliflorus",
Common_name:"Himalayan Cotoneaster ",
Picture: "images/Fplants/Cladothamnus pyroliflorus.png",
},...
This wouldn't seem like an issue with IndexedDB.
For non-Angular directive attributes, such as src you want to interpolate as in the code below:
<img src='{{item.Picture}}' width="100px;" height="100px;"/>
For Angular directive attributes, there's no need for such interpolation:
<img data-ng-src='item.Picture' width="100px;" height="100px;"/>
As your data is going to be undefined on bootstrap, you want to use the latter approach. It prevents the browser from trying to load undefined as an image source.
Also, please note vaibhav's comment above. Without a leading slash, you'll load the images directory as relative to the current. While that may be what you're going for, it's probably going to make your code more reusable to include the leading slash regardless.
Update: If you're in an ng-repeat, note that your scope is not the scope in which the ng-repeat directive appears but it's own, brand new scope. Perhaps try out $parent.item.Picture
I'm having the same problem, it occurs with the image filename having spaces in between , maybe we could write a directive the removes the space from the filename as I'm calling the image via other variable such as title..
app.config(['$routeProvider','$compileProvider',function($routeProvider, $compileProvider){ $compileProvider.imgSrcSanitizationWhitelist('img/');

AngularJS element directives not displaying when using self-closing tags

I have in my html file directives
<add />
<back />
and the directives are on the form
.directive('add', ['$window', ...
and
.directive('back', ['$window',
This works fine.
If i change the directives to camel case:
.directive('addPlayer', ['$window', ...
<add_player />
<back />
and
<add:player />
<back />
display fine whereas
<add-player /> regular dash
<back />
displays only <add-player> and everything after is not displayed.
Any ideas why?
EDIT:
I've kind of gotten the same behaviour here
http://plnkr.co/edit/cpP4c2TyZwv5Y4BrNUBb?p=preview
To lay your question to rest, I am quoting the official statement from the AngularJS team: (sic)
self-closing or void elements as the html spec defines them are very special to the browser parser. you can't make your own, so for your custom elements you have to stick to non-void elements (<foo></foo>).
this can't be changed in angular.
- IgorMinar
source: https://github.com/angular/angular.js/issues/1953#issuecomment-13135021
Follow the rest of the conversation on AngularJS issue's page where they discuss the possibility of using XHTML for delivering content with self-closing tags that is acceptable to the browser. However do note that it is not fully supported by AngularJS.
HTML spec does not allow self-closing tags on non-void elements.
HTML syntax rules [W3C]
Elements have a start tag to indicate where they begin. Non-void elements have an end tag to indicate where they end.
Start tags consist of the following parts, in exactly the following order:
A "<" character.
The element’s tag name.
Optionally, one or more attributes, each of which must be preceded by one or more space characters.
Optionally, one or more space characters.
Optionally, a "/" character, which may be present only if the element is a void element.
A ">" character.
There is a limited number of void elements in HTML5 spec. Here is the complete list:
area, base, br, col, command, embed, hr, img, input, keygen, link, meta, param, source, track, wbr.
What's really going on
The browser's parser has to listen to the spec. Since using the slash in a non-void element tag is invalid, the parser ignores the ending />, and <back /> means <back>. Therefore you are never closing the first element which prevents the others to work.
On Plunker you have:
<body>
<back></back>
Self closing <back />
Self closing <back />
</body>
which parses into
<body>
<back></back>
Self closing <back>
Self closing <back>
</back>
</back>
</body>
You then specify template: '<button>back</button>' on your directive which replaces back (and it's children) with the specified HTML resulting in:
<body>
<back>
<button>back</button>
</back>
Self closing <back>
<button>back</button>
</back>
</body>
What should I do then?
Use <back></back> for all and it will work fine. Alternatively you could use element attributes: <div back="attr"></div>.
See the following discussions for more details:
Q: Are self-closing tags valid in HTML5?
AngularJS - Custom directives with self-closing tags capture tag siblings.
AngularJS - Self-closing directives not always rendering.
I've run into the same problem recently and managed to fix it by not using self-closing tags. Try <add-player></add-player> instead of the self-closing version.
I don't know why self-closing tags don't work with dashes in the directive's tag name. Did a quick research back in the day and didn't find anything on the HTML/XHTML side. Perhaps a bug/limitation in Angular?
Angular v15.1.0 now has added support to self-closing tags on custom elements.
Check it out: https://github.com/angular/angular/blob/main/CHANGELOG.md

Resources