admin管理员组文章数量:1418410
I have $scope.myArray, and it's binding with an input field by ngModel and the expression {{myArray}}
My issue is when I modified myArray by call changeMyArray(), the input's value did not change. But the expression {{myArray}} is display new value.
So, Why the expression work but input field does not?
I have a way to do, but I want to find a better approach
var newArr = $scope.myArray;
newArr.push("b");
$scope.myArray = angular.copy(newArr);;
Example fiddle
I have $scope.myArray, and it's binding with an input field by ngModel and the expression {{myArray}}
My issue is when I modified myArray by call changeMyArray(), the input's value did not change. But the expression {{myArray}} is display new value.
So, Why the expression work but input field does not?
I have a way to do, but I want to find a better approach
var newArr = $scope.myArray;
newArr.push("b");
$scope.myArray = angular.copy(newArr);;
Example fiddle
Share Improve this question edited Mar 25, 2015 at 18:21 Tuan asked Mar 25, 2015 at 17:45 TuanTuan 612 silver badges10 bronze badges 5- 2 i dont see any input in your fiddle and it is pushing successfully? – A.B Commented Mar 25, 2015 at 17:49
- Your example fiddle doesn't have an input. Can you update the example to demonstrate your problem? – Austin Mullins Commented Mar 25, 2015 at 17:49
-
1
Can you also add the HTML code of how you are binding the
myArray
variable to the input field? If what you want is to use an input text field to push values into your array, then binding it to the whole array wont work. – Roberto Linares Commented Mar 25, 2015 at 17:50 - Sorry guys, I updated my link – Tuan Commented Mar 25, 2015 at 17:51
- You use a different variable name : countChange_watch and countChange when watching the array. – sirrocco Commented Mar 25, 2015 at 17:55
3 Answers
Reset to default 4Basically, I think what you want to do is bind the input to a "new entry" scope variable, and then push the value of that variable to your array when the user clicks "Push To". Here's what I mean:
In controller:
$scope.changeMyArray = function() {
$scope.myArray.push($scope.newEntry);
$scope.newEntry = "";
}
In HTML:
<input ng-model="newEntry">
But actually:
Really what you want is a way to edit the contents of an array via text, and have updates to that array from elsewhere also update the text. This is actually pretty simple since browsers e with a JSON library.
I implemented it by starting with a known pair of objects:
$scope.myArray = [];
$scope.myArrayString = "[]";
That way you can update the string via ngModel:
<input ng-model="myArrayString">
Watch for changes on this model to update the actual array:
$scope.$watch("myArrayString", function() {
$scope.myArray = JSON.parse($scope.myArrayString);
});
Then update the string in the changeMyArray
function:
$scope.changeMyArray = function() {
$scope.myArray.push("b"); // Or whatever you would like to add here
$scope.myArrayString = JSON.stringify($scope.myArray);
}
Experiment in my fork of the Fiddle.
What's going on?
The variable $scope.myArray
is an object, and any object in Javascript can be converted to a string (most plex objects end up as the unhelpful "[object Object]"
). Arrays will actually display their contents when converted to a string, so binding an array to HTML via {{myArray}}
is pretty straightforward.
However, the reverse conversion is not as simple. In general, a text input can't be bound to an array in a two-way fashion as we'd like. The solution, then, is to use an intermediary variable to hold the string value, and use $scope.$watch
to keep the two values in sync.
So you seem to be wondering why when pushing to the array, your $watch function doesn't do the increment. That's because the #watch function only checks object reference equality.
When pushing to the array, the reference stays the same. When you copy the array and set it again in the same variable, the reference changes.
That's why @watchCollection works as expected and increments when each item is pushed.
I have an explanation for my question. Please correct me if I wrong, very thank.
My Question: Why "myArray" input field does not update when $scope.myArray is changed (Model doesn't update View)?
<input ng-model="myArray" id="myArray">
The answer is AngularJs ng-model doesn't know $scope.myArray is changed. Because ng-model does not perform a deep watch of object (rather than a string or number), it only looks for a change of identity or pares the reference of the objects.
In my case, $scope.myArray is collection. So, although $scope.myArray has changed by push new item (structure is changed), it's reference does not change.
As the result, $setViewValue() and $render() never invoked to update the view.
$render $setViewValue
Solution:
Sol1: Add new item to $scope.myArray, make a copy of myArray object and then asign a copy to $scope.myArray again. By this way, the object reference is changed. AngularJs see that change and update the view.
var newArr = $scope.myArray;
newArr.push("b");
$scope.myArray = angular.copy(newArr);
Sol2: Create custome $watch('email', function(){...}, true). The last parameter is TRUE to let Angular perform a deep watch. Then, in watch's listener function, I manually set $viewValue = newValue and invoke $render() of ngModelController to update the view. In case we have Formatters, we should invokes them in this step.
$scope.$watch('myArray', function(newValue, oldValue) {
if (newValue !== oldValue) {
var ctrl = angular.element(document.querySelector('#myArray')).controller('ngModel');
// Invoke formatter
var formatters = ctrl.$formatters,
idx = formatters.length;
while(idx--) {
newValue = formatters[idx](newValue);
}
ctrl.$render();
}
}, true);
Please see my script
本文标签: javascriptAngularJSbinding array value to input ngModelStack Overflow
版权声明:本文标题:javascript - AngularJS - binding array value to input ngModel - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745271568a2650924.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论