I apologize in advance if i'm not wording this properly. I have a textbox with ng-model
inside an ng-repeat
and when I try to get the textbox value it's always undefined
. I just want it to display whatever I type in the corresponding textbox.
It seems to be an issue with the $scope
, so how would I make the $scope.postText
global or at the controller root level so it can be accessible?
Here's the JSFiddle to help clear things up: http://jsfiddle.net/stevenng/9mx9B/14/
AngularJS ng-repeat Directive The ng-repeat directive repeats a set of HTML, a given number of times. The set of HTML will be repeated once per item in a collection. The collection must be an array or an object. Note: Each instance of the repetition is given its own scope, which consist of the current item.
The ng-repeat values can be filtered according to the ng-model in AngularJS by using the value of the input field as an expression in a filter. We can set the ng-model directive on an input field to filter ng-repeat values.
Note: The $index variable is used to get the Index of the Row created by ng-repeat directive. Each row of the HTML Table consists of a Button which has been assigned ng-click directive. The $index variable is passed as parameter to the GetRowIndex function.
As @Gloopy already stated, ng-repeat creates a new child scope for each item in your posts
array. Since each item of the posts
array is a primitive (a string), ng-repeat also creates a post
property on each child scope, and assigns each of them the appropriate value from the array. Inside the ng-repeat block is ng-model="postText"
. This creates a postText property on each of the child scopes. Here is what that all looks like (for 2 of the 4 child scopes):
When a user types some text into one of the input textboxes, the appropriate gray box will store the text. (E.g., the 2nd (from the top) gray box will store text a user types into the "tech" textbox.) The parent scope cannot see the postText properties in the child scope -- this is the problem you had. There are three common solutions:
posts
array. E.g.,$scope.posts = [ {type: 'tech'}, {type: 'news'}, ...];
<input type="text" ng-model="post.postText">
posts
, rather than a copy (of a value). Therefore, post.postText
gets created on parent $scope property posts
, and hence it is visible to the parent scope. (So, in this case the child scopes would simply call savePost()
-- there would be no need to pass any values up to the parent scope.)posts
array in the parent would be automatically updated as follows:$scope.posts = [ {type: 'tech', postText: 'this is tech related'}, {type: 'news'}, ...];
ng-model="$parent.someProperty"
to bind the form element to a property on the parent scope, rather than on the child scope. This solution would be difficult to implement for your scenario, and it is a rather fragile solution, as it depends on the HTML structure for scope inheritance... but I mention it for completeness.(A fourth solution was presented by @Renan in comments on @Gloopy's answer. This is a like solution 1., but with a variation: this
is used instead of passing a value up to the parent. I'm not a fan of this approach as it makes it difficult to determine which $scope is being accessed or modified. I think it is better that functions defined on $scope only access and modify their own $scope.)
For more information (and lots more pictures) about how prototypal scope inheritance works in Angular, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
In your click expression you can reference the postText
and access it in your savePost
function. If this wasn't in an ng-repeat you could access the single $scope.postText
successfully but ng-repeat creates a new scope for each item.
Here is an updated fiddle.
<div ng-repeat="post in posts">
<strong>{{post}}</strong>
<input type="text" ng-model="postText">
<a href="#" ng-click="savePost(postText)">save post</a>
</div>
$scope.savePost = function(post){
alert('post stuff in textbox: ' + post);
}
This may be a late answer. Please refer this fiddle. http://jsfiddle.net/X5gd2/ Please refer to the firebug's console, when u click on the links after typing some texts in the text box. The idea is to have a itemcontroller for each of the view that is repeated inside the ng-repeat.
The item controller:
function postItemController($scope){
$scope.savePost = function(){
console.log($scope.postText + " which belongs to " + $scope.post +" will be saved")
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With