Answering your first question:
I have noticed that when I input text into the box, it does not appear in the {{x2}} output
This occurs because in Javascript, literals like x1
and x2
are not passed by reference, unlike objects. If you had used an object to reference the value, it would have worked. For instance:
var m = angular.module("m1", []);
m.controller('c', function($scope) {
$scope.x1 = {myModel: ''};
$scope.x2 = $scope.x1;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<div ng-app="m1" ng-controller='c'>
<input ng-model="x1.myModel">
<br>
<span>{{x2.myModel}}</span>
</div>
The above example works because x1
is an object and its reference is passed when assigned to x2
. This was not the case with plain literal strings like x1
.
However, using angular.copy
to clone the object will not work as expected. Consider this scenario:
var m = angular.module("m1", []);
m.controller('c', function($scope) {
$scope.x1 = {myModel: ''};
$scope.x2 = angular.copy($scope.x1);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<div ng-app="m1" ng-controller='c'>
<input ng-model="x1.myModel">
<br>
<span>{{x2.myModel}}</span>
</div>
Using angular.copy
creates a clone of the object rather than passing by reference, leading to a similar problem like before.
Addressing your second question:
Interestingly, using a function resolves the issue
In Angular, when you create a scope function and use it in the view (e.g., {{x2()}}
), Angular automatically updates the view whenever the function's returned value (x2()
) changes.
Possible Solutions:
Several solutions have been suggested by others to tackle this issue.
Option 1: Utilize $watch
(https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch)
var m = angular.module("m1", []);
m.controller("c", function($scope) {
$scope.$watch("x1", function(newValue) {
$scope.x2 = $scope.x1;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<div ng-app="m1" ng-controller='c'>
<input ng-model="x1">
<br>
<span>{{x2}}</span>
</div>
Option 2: Use ng-change
(https://docs.angularjs.org/api/ng/directive/ngChange)
var m = angular.module("m1", []);
m.controller("c", function($scope) {
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<div ng-app="m1" ng-controller='c'>
<input ng-model="x1" ng-change="x2 = x1">
<br>
<span>{{x2}}</span>
</div>
No additional Javascript code is necessary for this approach.
Option 3: Use Objects Instead
To avoid such issues, consider using objects instead of plain string literals.
Option 4: Employ Functions
You can also leverage Angular functions, as highlighted in your initial query.