19

如果我措辞不当,我提前道歉。我有一个带有ng-model内部的文本框ng-repeat,当我尝试获取文本框值时,它总是undefined. 我只希望它显示我在相应文本框中输入的任何内容。

这似乎是一个问题$scope,那么我将如何制作$scope.postText全局或控制器根级别以便可以访问它?

这是帮助解决问题的 JSFiddle:http: //jsfiddle.net/stevenng/9mx9B/14/

4

4 回答 4

45

posts正如@Gloopy 已经说过的, ng-repeat 为数组中的每个项目创建一个新的子范围。由于posts数组中的每一项都是原始的(字符串),ng-repeat 还在post每个子作用域上创建一个属性,并为它们中的每一个分配数组中的适当值。ng-repeat 块内部是ng-model="postText". 这会在每个子作用域上创建一个 postText 属性。这是所有的样子(对于 4 个子范围中的 2 个):

ng-重复范围

当用户在其中一个输入文本框中键入一些文本时,相应的灰色框将存储文本。(例如,第二个(从顶部开始)灰色框会将用户键入的文本存储到“技术”文本框中。)父范围无法看到子范围中的 postText 属性——这就是您遇到的问题。常见的解决方案有以下三种:

  1. @Gloopy 的答案:在父作用域上定义一个函数(子作用域可以访问,因为 ng-repeat 子作用域原型从父作用域继承)并将子作用域属性值(即 postText 的值)传递给父作用域。
  2. posts在数组中使用对象而不是基元。例如,
    $scope.posts = [ {type: 'tech'}, {type: 'news'}, ...];
    然后在您的 ng-repeat 循环中,使用
    <input type="text" ng-model="post.postText">
    因为每个数组项都是一个对象(而不是原始对象),所以每个子作用域都获得对数组中适当对象的引用posts,而不是(值的)副本。因此,post.postText在父 $scope 属性上创建posts,因此它对父范围可见。(因此,在这种情况下,子作用域会简单地调用savePost()——不需要将任何值传递给父作用域。)
    换句话说,如果用户在第一个文本框中键入“这是技术相关的”,父级中的posts数组将自动更新如下:
    $scope.posts = [ {type: 'tech', postText: 'this is tech related'}, {type: 'news'}, ...];
    最后一点:在用户键入内容之前,不会将 postText 属性添加到帖子对象中。
  3. 用于ng-model="$parent.someProperty"将表单元素绑定到父作用域上的属性,而不是子作用域上的属性。这个解决方案很难为您的场景实施,而且它是一个相当脆弱的解决方案,因为它依赖于范围继承的 HTML 结构......但我提到它是为了完整性。

(@Renan 在对@Gloopy 的回答的评论中提出了第四个解决方案。这与解决方案 1 类似,但有一个变体:this用于代替将值传递给父级。我不喜欢这种方法因为它很难确定正在访问或修改哪个 $scope。我认为在 $scope 上定义的函数最好只访问和修改自己的 $scope。)

有关 Angular 中原型范围继承如何工作的更多信息(以及更多图片),请参阅AngularJS 中范围原型/原型继承的细微差别是什么?

于 2013-01-05T22:46:13.863 回答
25

在您的点击表达式中,您可以引用并在您的函数postText中访问它。savePost如果这不在 ng-repeat 中,您可以$scope.postText成功访问单个,但ng-repeat会为每个项目创建一个新范围。

是一个更新的小提琴。

<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);
}
于 2012-08-01T05:42:29.813 回答
2

这可能是一个迟到的答案。请参考这个小提琴。http://jsfiddle.net/X5gd2/ 请参考firebug的控制台,当你在文本框中输入一些文本后点击链接。这个想法是为在 ng-repeat 中重复的每个视图都有一个 itemcontroller。

项目控制器:

function postItemController($scope){
    $scope.savePost = function(){
        console.log($scope.postText + " which belongs to " + $scope.post +" will be saved")
    }
}
于 2013-02-27T22:46:01.583 回答
1

将模型拆分为标题和值

angular.module('MyApp',[]);

function PostCtrl($scope) {
     $scope.posts = [{heading:'tech',value:''}, {heading:'news',value:''},     {heading:'sports',value:''},{heading:'health',value:''}];

    $scope.savePost = function(post){
        alert( 'post stuff in textbox: ' + post);
    }
}

下面的HTML..

<div ng-app="MyApp">
    <div ng-controller="PostCtrl">
        <div ng-repeat="post in posts">
          <strong>{{post.heading}}</strong>
          <input type="text" ng-model="post.value"> 
          <a href="#" ng-click="savePost(post.value)">save post</a>   
        </div>
    </div>
</div>

看看这个小提琴..

于 2014-10-07T04:26:00.003 回答