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:
- @Gloopy's answer: define a function on the parent scope (which the child scopes can access, because ng-repeat child scopes prototypically inherit from the parent scope) and pass the child scope property value (i.e., postText's value) up to the parent.
- Use objects instead of primitives in your
posts
array. E.g.,
$scope.posts = [ {type: 'tech'}, {type: 'news'}, ...];
Then in your ng-repeat loop, use
<input type="text" ng-model="post.postText">
Because each array item is an object (and not a primitive), each child scope gets a reference to the appropriate object in array 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.)
In other words, if a user typed "this is tech related" into the first text box, the posts
array in the parent would be automatically updated as follows:
$scope.posts = [ {type: 'tech', postText: 'this is tech related'}, {type: 'news'}, ...];
One last note: the postText property is not added to the posts object until the user types something.
- Use
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?