Using itemprop attributes with AngularJS - javascript

I am making some changes to a cart which was built using AngularJS, one of my tasks is to add itemprop attributes to existing markup eg.
<span itemprop="color">{{colourOption.colour.code}}</span>
The problem is that this value gets interpolated much later after an Ajax call returns, so any webcrawler or whatever wants to access this itemprop doesn't get the interpolated value, it gets the angular expression instead.
Is there a way around this?

You can use the ng-bind directive to mask your templating in the event of web-crawlers.
<div ng-bind='colourOption.colour.code'>This is search-engine friendly text.</div>

Related

How to parse a html string to native angular template

Currently I'm rendering the html string using innerHtml property after bypassing the angular sanitizing mechanism this is working for rendering the contents. But not able to map the event handlers to a function in angular component.
E.g.the html string will contain a button like below
<button (click)="callme()">Click</button>
the callme function will be part of angular component file. I want this click event to be handled in angular function.
Is it possible to parse this string to html dom and handle the events in angular components.
Sample code which describes this scenario and using angular cdk Portals.
https://stackblitz.com/edit/angular-upaudh?file=src%2Fapp%2Fcdk-portal-overview-example.ts
There are 2 ways that you can implement it, it depends from what you want.
The easy way is to use innerHtml input like this:
HTML
<div [innerHTML]="htmlStr"></div>
TS
htmlStr: 'Hello';
If you want to create a dynamic template that will be translated to HTML at build time. Then you have to go with Portals.
PS: In your example (in the comments) you use [innerHtml] and try to bind it in a Portal. Again [innerHtml] will not be translated before runtime so your click event will not be in the same scope as your component. The thing that you ask is an open conversation in github: Issue. For now you can use the alternatives above to solve your case. You can use innerHtml, and then use renderer2 or native element reference to bind click events to your functions, after they have rendered on the view.

Jade / Pug: Hide div unless variable has data

I want to hide a div unless the div has received data to the local variable. I have this at the moment:
div#cost
p You earn #{cost} a day!
But it displays on the page. How do I hide it until it receives the data? Im confused about Jade's if/else syntax
-if (cost)
div#cost
p You earn #{cost} a day!
First of all, the - means that it is unbuffered Javascript code. Meaning this will not get rendered in the final version of the template. If you would want that, you should use a script tag like so: script..
Second, the if-statement will check if cost is not equal to null or undefined. When it doesn't exists, the code inside the if-statement will be skipped.
The above code will result in the following HTML if cost is not equal to null or undefined:
<div id="cost">
<p>You earn ... cost a day!</p>
</div>
What you are trying to achieve is not possible.
jade/pug is a template engine, you can give placeholder variable, perform loops, conditions etc but your browser does not understand jade/pug it understands only HTML, which means your template will be converted to a static HTML content before being displayed.
The if/else block decide what is going to be part of the generated HTML file, once the file is generated jade/pug does not have any control over it.
If you want to dynamically control your DOM you can use a web framework such as Angular, Vue, React or you can do DOM manipulation using jQuery or by hand with regular Javascript.

Angular-formly: Why does the directive behave differently from the type?

I have two input fields, both generated by the same template. On both I am setting
...
templateOptions: {
...
required: true
}
One input field is registered using formlyConfig.setType
the other using a directive. I have created a JS Bin here.
Only the first is getting the required attribute, the second is not. In the docs for custom templates (controller option) it says:
Provides you the ability to add custom behavior to the type without having to make an entire directive (you can make a directive instead if you wish).
What am I doing wrong?
The problem in the second example that when angular-formly is processing the options with the template, all angular-formly sees is: <plain-text> for the template. Hence, it doesn't know what element to place the required attribute on. angular-formly will only attach attributes like these to elements that have an ng-model on them because those are the only elements where that attribute makes sense.
Again, the key here is what angular-formly sees when it's processing the template (before it's compiled). It doesn't matter what the directive compiles to. So yes, you can use your own directive, but if you want to leverage the features of angular-formly, it needs to utilize the ng-model controller (like directive used in this example).
Good luck!

Is "data-bind" a strictly knockout-only attribute?

I know that one can always define own custom attributes for an HTML tag.
I also know that data-bind is the keyword knockout.js chose as the HTML attribute that links the data to the UI.
So far so good.
What I am curious to know is whether when I come across HTML on some website and I see that it uses the attribute data-bind, does it always imply it uses knockout.js?
<span class="chk" data-bind="visible: selectedAnswers().length > 0" />
In other words, what is the likelihood that a website using the data-bind attribute is not using knockout.js?
No it's not... I've used data-bind in projects not involving knockout. As long as it makes sense as to what the data is going to be used for then you can use whatever string you want (within reason, see below)...
data-bind=""
data-binder=""
data-im-a-data-attribute=""
The data-* attributes consist of two parts:
1) The attribute name should not contain any uppercase letters, and must be at least one character long after the prefix "data-"
2)The attribute value can be any string
Info obtained from here
Knockout uses the data-bind attribute, but it's just a subset of the HTML5 data-* attributes. They allow for extra data to be stored in an element that don't follow standard HTML attributes.
From https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes :
data-* attributes allow us to store extra information on standard, semantic HTML elements without other hacks such as classList, non-standard attributes, extra properties on DOM, or setUserData.
So anyone can use an attribute named data-bind, Knockout chose to use that because it made sense for them.

AngularJS : Why ng-bind is better than {{}} in angular?

I was in one of the angular presentation and one of the person in the meeting mentioned ng-bind is better than {{}} binding.
One of the reason, ng-bind put the variable in the watch list and only when there is a model change the data get pushed to view, on the other hand, {{}} will interpolate the expression every time (I guess it is the angular cycle) and push the value, even if the value changed or not.
Also it is said that, if you have not much data in on the screen you can use {{}} and the performance issue will not be visible. Can someone shed some light on this issue for me?
Visibility:
While your angularjs is bootstrapping, the user might see your placed brackets in the html. This can be handled with ng-cloak. But for me this is a workaround, that I don't need to use, if I use ng-bind.
Performance:
The {{}} is much slower.
This ng-bind is a directive and will place a watcher on the passed variable.
So the ng-bind will only apply, when the passed value does actually change.
The brackets on the other hand will be dirty checked and refreshed in every $digest, even if it's not necessary.
I am currently building a big single page app (~500 bindings per view). Changing from {{}} to strict ng-bind did save us about 20% in every scope.$digest.
Suggestion:
If you use a translation module such as angular-translate, always prefer directives before brackets annotation.
{{'WELCOME'|translate}} => <span ng-translate="WELCOME"></span>
If you need a filter function, better go for a directive, that actually just uses your custom filter. Documentation for $filter service
UPDATE 28.11.2014 (but maybe off the topic):
In Angular 1.3x the bindonce functionality was introduced. Therefore you can bind the value of an expression/attribute once (will be bound when != 'undefined').
This is useful when you don't expect your binding to change.
Usage:
Place :: before your binding:
<ul>
<li ng-repeat="item in ::items">{{item}}</li>
</ul>
<a-directive name="::item">
<span data-ng-bind="::value"></span>
Example:
ng-repeat to output some data in the table, with multiple bindings per row.
Translation-bindings, filter outputs, which get executed in every scope digest.
If you are not using ng-bind, instead something like this:
<div>
Hello, {{user.name}}
</div>
you might see the actual Hello, {{user.name}} for a second before user.name is resolved (before the data is loaded)
You could do something like this
<div>
Hello, <span ng-bind="user.name"></span>
</div>
if that's an issue for you.
Another solution is to use ng-cloak.
ng-bind is better than {{...}}
For example, you could do:
<div>
Hello, {{variable}}
</div>
This means that the whole text Hello, {{variable}} enclosed by <div> will be copied and stored in memory.
If instead you do something like this:
<div>
Hello, <span ng-bind="variable"></span>
</div>
Only the value of the value will be stored in memory, and angular will register a watcher (watch expression) which consists of the variable only.
Basically the double-curly syntax is more naturally readable and requires less typing.
Both cases produce the same output but.. if you choose to go with {{}} there is a chance that the user will see for some milliseconds the {{}} before your template is rendered by angular. So if you notice any {{}} then is better to use ng-bind.
Also very important is that only in your index.html of your angular app you can have un-rendered {{}}. If you are using directives so then templates, there is no chance to see that because angular first render the template and after append it to the DOM.
{{...}} is meant two-way data binding. But, ng-bind is actually meant for one-way data binding.
Using ng-bind will reduce the number of watchers in your page. Hence ng-bind will be faster than {{...}}. So, if you only want to display a value and its updates, and do not want to reflect its change from UI back to the controller, then go for ng-bind. This will increase the page performance and reduce the page load time.
<div>
Hello, <span ng-bind="variable"></span>
</div>
This is because with {{}} the angular compiler considers both the text node and it's parent as there is a possibility of merging of 2 {{}} nodes. Hence there are additional linkers that add to the load time. Of course for a few such occurrences the difference is immaterial, however when you are using this inside a repeater of large number of items, it will cause an impact in slower runtime environment.
The reason why Ng-Bind is better because,
When Your page is not Loaded or when your internet is slow or when your website loaded half, then you can see these type of issues (Check the Screen Shot with Read mark) will be triggered on Screen which is Completly weird. To avoid such we should use Ng-bind
ng-bind has its problems too.When you try to use angular filters, limit or something else, you maybe can have problem if you use ng-bind. But in other case, ng-bind is better in UX side.when user opens a page, he/she will see (10ms-100ms) that print symbols ( {{ ... }} ), that's why ng-bind is better.
There is some flickering problem in {{ }} like when you refresh the page then for a short spam of time expression is seen.So we should use ng-bind instead of expression for data depiction.
ng-bind is also safer because it represents html as a string.
So for example, '<script on*=maliciousCode()></script>' will be displayed as a string and not be executed.
According to Angular Doc:
Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading... it's the main difference...
Basically until every dom elements not loaded, we can not see them and because ngBind is attribute on the element, it waits until the doms come into play... more info below
ngBind
- directive in module ng
The ngBind attribute tells AngularJS to replace the text content of the specified HTML element with the value of a given expression, and to update the text content when the value of that expression changes.
Typically, you don't use ngBind directly, but instead you use the double curly markup like {{ expression }} which is similar but less verbose.
It is preferable to use ngBind instead of {{ expression }} if a template is momentarily displayed by the browser in its raw state before AngularJS compiles it. Since ngBind is an element attribute, it makes the bindings invisible to the user while the page is loading.
An alternative solution to this problem would be using the ngCloak directive. visit here
for more info about the ngbind visit this page: https://docs.angularjs.org/api/ng/directive/ngBind
You could do something like this as attribute, ng-bind:
<div ng-bind="my.name"></div>
or do interpolation as below:
<div>{{my.name}}</div>
or this way with ng-cloak attributes in AngularJs:
<div id="my-name" ng-cloak>{{my.name}}</div>
ng-cloak avoid flashing on the dom and wait until all be ready! this is equal to ng-bind attribute...
You can refer to this site it will give you a explanation which one is better as i know {{}} this is slower than ng-bind.
http://corpus.hubwiz.com/2/angularjs/16125872.html
refer this site.

Categories

Resources