Riley Lark
Riley Lark

Reputation: 20890

Bind once in angular... and then again on each event

I've got a 400kb picture in a data url in my scope. I'm using <img ng-src='{{dataUrl}}'/>, which is working, but extremely slowly: I assume angular is checking this 400kb value against itself every single frame. The angularjs batarang confirms that 95% of my total run time is spent $watching {{dataUrl}}.

The dataUrl CAN change dynamically, but certainly not every frame - only when the user selects a new image.

How can I blast a new dataUrl into the DOM on events without using the full two-way binding features that are becoming so expensive?

Upvotes: 0

Views: 4613

Answers (3)

Andr&#233; Bueno
Andr&#233; Bueno

Reputation: 89

You can use one-way-databiding, like this

<img ng-scr="{{::dataUrl}}"/>

Or if you are using an angular version bigger than 1.3 there is an one bind embedded. That you can use on almost any directive. The $digest list will handled the watches only once, after loaded they will be destroyed.

Upvotes: 1

Ayobami Opeyemi
Ayobami Opeyemi

Reputation: 752

The $watch function returns a callback just for that. You just have to execute it back to destruct the watcher.

var watcher = $scope.$watch('data', function(newValue, oldValue) {
if (newValue) {//you could do a isset here

    watcher();
}
});

To re-watch. Might be expensive depending on the number of items on the current $scope

if(!$scope.$$phase) {
    $scope.$digest()
}

Upvotes: 2

Alex Choroshin
Alex Choroshin

Reputation: 6187

You can use bindonce - a high performance one time binding for AngularJS that can render your results in 0 watches.

Example:

<ul>
<li bindonce ng-repeat="person in Persons">
    <a bo-href="'#/people/' + person.id"><img bo-src="person.imageUrl"></a>
    <a bo-href="'#/people/' + person.id" bo-text="person.name"></a>
    <p bo-class="{'cycled':person.generated}" bo-html="person.description"></p>
</li></ul>

or:

<div bindonce="Person" bo-title="Person.title">
<span bo-text="Person.firstname"></span>
<span bo-text="Person.lastname"></span>
<img bo-src="Person.picture" bo-alt="Person.title">
<p bo-class="{'fancy':Person.isNice}" bo-html="Person.story"></p>

Update:

another One time binding for AngularJS as suggested by Ilan Frumer

Example:

<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>

Upvotes: 2

Related Questions