Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I don't understand Angular data binding at all

I've spent several hours trying minor variations of this code, and I don't understand why one works and the other doesn't.

Here's the scenario: I'm trying to present a list of registered users (which I'm getting with a simple database query that returns just a few columns), then when one user's name is clicked on, I'll retrieve more information about that user from the database, and present it in a different view. At the moment, I'm doing this with regular <a> elements with an ng-click directive that sets a value called currentid. Elsewhere in my code, I use $watch() to send out a new database query whenever currentid changes. That part seems to be working (I see the console.log() output from my watch callback, and the database query is spitting out the right data)... but sometimes currentid changes, and sometimes it doesn't, and I cannot figure out why.

  • A jsfiddle where it doesn't work: http://jsfiddle.net/aLcRL/11/
  • A jsfiddle where it DOES work: http://jsfiddle.net/aLcRL/12/

(Click on the "rmunn" and "admin" links in the table: the "Currrent ID" value below should update. And please pardon the almost total lack of CSS; I'm a coder, not a graphics designer ("Dammit, Jim!"), and it's also very late in my timezone right now so I have no motivation to pretty this up. It's functional, it demonstrates the problem, and I'm going to leave it at that.)

The only difference between these two is that one is binding to currentid, and the other is binding to vars.currentid. Now, I understand why binding to currentid wouldn't work in the case of a parent and a child scope (the child's value would overshadow the parent's value); since I'm coming from a Python background, this makes sense to me (it's similar to how Python's instance namespaces can shadow the namespaces of anything defined on the class). But in this jsfiddle, I'm only using one controller -- aren't all these variables in the same scope?

I've been beating my head against this all day, and the several Stack Overflow answers I've tried to read (like How does data binding work in AngularJS? for example) have just left me even more confused: $apply() and $digest() and scopes, oh my! So if anyone can give me a nice simple beginner's guide to scopes in Angular (or point me to an already-written one that I've missed), I'd be very grateful.

"I've learned Clojure and Haskell, I can learn a simple Javascript framework," I thought. "This'll be easy." Boy, was I wrong. :-)

like image 832
rmunn Avatar asked Jun 18 '13 16:06

rmunn


People also ask

What does data binding mean in Angular?

Data binding in AngularJS is the synchronization between the model and the view. When data in the model changes, the view reflects the change, and when data in the view changes, the model is updated as well.

What are the 3 types of data binding available with Angular?

As mentioned earlier, one-way data binding in Angular can be of three types i.e Interpolation, Property binding, and Event binding.

What is data binding in Angular with example?

Two-way data binding is a two-way interaction, data flows in both ways (from component to views and views to component). Simple example is ngModel. If you do any changes in your property (or model) then, it reflects in your view and vice versa. It is the combination of property and event binding.

How many ways we can bind data in Angular?

Types of data bindinglink Angular provides three categories of data binding according to the direction of data flow: From source to view. From view to source. In a two-way sequence of view to source to view.


1 Answers

You are running into an issue where ng-repeat creates a child scope.

<tr ng-repeat="user in data" blarg="{{user.id}}">
    <!-- currentid here is part of the ng-repeat child scope 
     and not your root scope -->
    <td><a href="#{{user.id}}" ng-click="currentid = user.id">{{user.userName}}</a></td>
    <td>{{user.email}}</td>
</tr>

If you need to access the parent scope you can use $parent.currentid

<a href="#{{user.id}}" ng-click="$parent.currentid = user.id">{{user.userName}}</a>

You need to use $apply() whenever you modify a value outside of the angular world. For example using setTimeout() or a jQuery Plugin. Calling $apply() alerts Angular to reevaluate the scope to see if anything changed and update accordingly.

like image 190
Mark Coleman Avatar answered Oct 08 '22 01:10

Mark Coleman