Render value without data-binding
Solution 1
Angular 1.3+
In 1.3, Angular has supported this using the following syntax.
<div>{{::message}}</div>
As mentioned in this answer.
Angular 1.2 and below
This is simple and doesn't need a plugin. Check this out.
This small directive will easily accomplish what you are trying to achieve
app.directive('bindOnce', function() {
return {
scope: true,
link: function( $scope ) {
setTimeout(function() {
$scope.$destroy();
}, 0);
}
}
});
You can bind once like this
<div bind-once>I bind once - {{message}}</div>
You can bind like normal
<div ng-bind="message" bind-once></div>
Demo: http://jsfiddle.net/fffnb/
Some of you may be using angular batarang, and as mentioned in the comments if you use this directive the element still shows as binding when it is not, I am pretty sure this has something to do with the classes that are attached to the element so try this, it should work (not tested). Let me know in the comments if it worked for you.
app.directive('bindOnce', function() {
return {
scope: true,
link: function( $scope, $element ) {
setTimeout(function() {
$scope.$destroy();
$element.removeClass('ng-binding ng-scope');
}, 0);
}
}
});
@x0b: If you have OCD and you want to remove the empty class
attribute do this
!$element.attr('class') && $element.removeAttr('class')
Solution 2
It looks like Angular 1.3 (starting with beta 10) has one-time binding built in:
https://docs.angularjs.org/guide/expression#one-time-binding
One-time binding
An expression that starts with :: is considered a one-time expression. One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value (see value stabilization algorithm below).
Solution 3
Use the bindonce module. You'll need to include the JS file and add it as a dependency to your app module:
var myApp = angular.module("myApp", ['pasvaz.bindonce']);
This library allows you to render items that are bound only once — when they are first initialized. Any further updates to those values will be ignored. It's a great way to reduce the number of watches on the page for things that won't change after they are rendered.
Usage example:
<div bo-text="value"></div>
When used like this, the property under value
will be set once it is available, but then the watch will be disabled.
Solution 4
Comparison between @OverZealous and @Connor answers :
With the traditional ngRepeat of angular : 15s for 2000 rows and 420mo of RAM (Plunker)
With ngRepeat and the module of @OverZealous : 7s for 2000 rows and 240mo of RAM(Plunker)
With ngRepeat and the directive of @Connor : 8s for 2000 rows and 500mo of RAM (Plunker)
I made my tests with Google Chrome 32.
Solution 5
As an alternative, there is angular-once
package:
If you use AngularJS, have performance issues and need to display lots of readonly data, this project is for you!
angular-once
was actually inspired by bindonce
and provides similar once-*
attributes:
<ul>
<li ng-repeat="user in users">
<a once-href="user.profileUrl" once-text="user.name"></a>
<a once-href="user.profileUrl"><img once-src="user.avatarUrl"></a>
<div once-class="{'formatted': user.description}" once-bind="user.description"></div>
</li>
</ul>
Blowsie
I'm an enthusiastic freelance designer and coder based in the United Kingdom. Key web based skills: Prototyping Coding Cross-browser Support Mobile Interfaces Testing Search Engine Optimisation Social Media Email Marketing HTML Semantics
Updated on July 08, 2022Comments
-
Blowsie almost 2 years
In AngularJS, how can I render a value without 2-way data binding? One may want to do this for performance reasons, or even rendering a value at a given point in time.
The following examples both use data binding:
<div>{{value}}</div>
<div data-ng-bind="value"></div>
How do I render
value
without any data binding? -
Mark Rajcok over 10 yearsI was about to write an answer "write your own directive ...", but it looks like someone has already done that for us, nice.
-
OverZealous over 10 yearsBindonce is useful enough that it could be included as a built-in optional library, like
$resource
. -
Blowsie over 10 yearsthis is what i was looking for, however I was expecting something like this to be built into angular!
-
Blowsie over 10 yearsim yet to test the plugin, but I would assume the AngularJS chrome tools would not show the bind-once element as a binding, where as your example does. Interesting approach tho, I will test both approaches soon.
-
Blowsie over 10 yearsSee this - it shows both as bindings dl.dropboxusercontent.com/u/14037764/Development/stackoverflow/…
-
iConnor over 10 yearsWithout a doubt that is because if the ng-binding class that you can easily remove
-
iConnor over 10 yearsIn the setTimeout remove the ng-binding and ng-scope classes
-
Yaron over 10 yearsThis is great and much simpler than the bindonce plugin. I added an ability to wait for a condition before destroying the scope and it's really helpful. thanks.
-
Robert Koritnik over 10 yearsWouldn't it be better to use
$timeout
to make it testable? -
iConnor over 10 years@RobertKoritnik I can't see any advantages using
$timeout
, it will be doing more operations that I don't think are needed, of course you can do though, if you wish -
x0b about 10 yearsFor those who want to remove a redundant empty class attribute then add this: if ($element.attr('class') === '') { $element.removeAttr('class'); }
-
iConnor about 10 years@x0b cheers, I've done that before, it does get annoying I'll add a reference in the answer.
-
XDS almost 10 yearsThis answer again and again. I can't praise you enough Karl! I highly recommend the agressive usage of this feature wherever it makes sense.
-
JSager almost 10 yearsWow I am really glad I scrolled down. I'm going to ask Connor to reference this in his accepted answer.
-
Billy G almost 10 yearsI have a table / list with 2000 lines and using the one-time-binding operator my app gets extremely slow when first showing / rendering the list. So slow, that the browser asks me two or three times if I want to stop executing the script!
-
James Daily almost 10 years@billy-g Can you post a jsfiddle or plunker illustrating the issue?
-
Billy G almost 10 years@James Daily: Here is the "normal" case plnkr.co/edit/rCRP0T5fSgNIllx7F27y and here the "one-time expression" case plnkr.co/edit/Rd5VBVjkcX3sTJYGypUr but... I can not reproduce it there. Anyway, it isn't faster with the "one-time expression" and I have to do more investigation to find why it happens in my environment (I use 1.3 beta 18 of angularjs)
-
SirTophamHatt over 9 yearsHow does this work for deferred objects on a scope? The bind-once is destroying the scope before the property I want to bind-once is resolved.
-
iConnor over 9 years@SirTophamHatt that defeats the object of "bind once", if your property isn't resolved then the first bound value will be undefined, you're going to need a different solution for a different problem
-
SirTophamHatt over 9 years@Connor I disagree. For example, I'm receiving a video object ($scope.video) from a REST API and I want one-time binding of the video title ($scope.video.title). Even if I resolve the promise BEFORE adding it to the scope in the controller, I still have to declare ng-bind="video.title" bind-once on the DOM. Now, before the promise gets resolved, video.title is undefined, and the scope gets destroyed before video.title is defined. A solution I have for this is to wrap the elements in some type of loading/init flag, ng-if="someLoadingFlag", but it's a poor pattern.
-
alecxe over 9 yearsWould be nice to also have
angular-once
compared. Thanks. -
Gabriel over 9 years@alecxe : I planned to do the tests when a stable build of AngularJS 1.3 be published.
-
alecxe over 9 yearsThanks, don't forget to include
angular-once
package (I've posted it as an alternative option here). -
Yaniv Efraim over 9 years@Connor - the "$scope.$destroy" will not remove the $watch (on angular 1.2). Any ideas how this could be fixed? see stackoverflow.com/questions/27400422/…
-
Augustin Riedinger almost 9 yearsAfter struggling for a while, I made a Question regarding the Batarang thing: stackoverflow.com/questions/32012004/…