I'm in the middle of trying to get my head around the data binding capabilities of AngularJS and have sort of a newbie question:
In the sample below, when I type a name into the textbox, the greeting doesn't update.
<html ng-app>
<head>
<script src="js/angular.js"></script>
<script>
function myCtl($scope){
$scope.person=$scope.fname;
}
</script>
</head>
<body>
<div ng-controller="myCtl">
<input ng-model="fname"/>
<br/>
Hello, {{person}}
</div>
</body>
When I change
Hello, {{person}}
to
Hello, {{fname}}
The greeting updates as I type. I'm confused about why the second syntax works but not the first.
$scope.person=$scope.fname creates a person primitive property on the $scope object and assigns it the value undefined (because $scope.fname does not yet exist when this line of code is executed). This is what your $scope looks like before you type into the textbox:

After you type something into the textbox, Angular automatically creates a fname primitive property on the $scope, and automatic two-way databinding continually sets the value to whatever is in the textbox. So, if I type "Mark", then $scope now looks like this:

It should be clear now why {{person}} shows nothing, but {{fname}} shows what is in the textbox.
Because, when you are typing in the input field, $scope.fname is changing, not $scope.person.
You could fix it with a $watch on fname:
$scope.$watch('fname', function(value) {
if(value) {
$scope.person = value;
}
}, true);
To asgoth's answer I would also add that this code belies a misunderstanding:
$scope.person=$scope.fname;
This code is not run each time something happens in the view but only once when your controller is executed. You seem to be trying to set $scope.person to the value in $scope.fname. But $scope.fname is not defined - that's what your controller needs to do. Your view and controller are therefore both referencing an undefined value.
In a simple case like this your controller should just initialize your model when it starts:
function myCtl($scope){
scope.person = {
fname: '',
lname: '',
email: ''
};
}
and you then bind elements to properties of person (e.g. ng-model="person.fname").
Now, whenever code runs in your controller, it automatically has the correct person.fname angular takes care of that for you - you never need to "read from your view".
function myCtl($scope){
$scope.person = {
fname: '',
lname: '',
email: ''
};
function validate() {
if (!$scope.email.match(/@/) return window.alert('Please enter a valid email address!');
}
}
From your view you would then do:
<form ng-submit="validate()">
or
<button ng-click="validate()">