在angularjs中使用模型和循环形式的惯用方法

时间:2013-02-03 01:00:53

标签: angularjs

如果我在AngularJS中为博客构建索引页面,请使用以下注释:

<li ng-repeat="post in posts">
    <h2>{{post.title}}
    <p>{{post.description}}</p>
    <h3>Leave a comment</h3>
    <form ng-submit="postComment()">
       <input type="hidden" value="{{post.id}}">
       Name: <input type="text"> <br>
       Comment: <textarea></textarea> <br>
       <input type="submit" value="Post comment">
    </form>
</li>

我无法弄清楚将模型与要从控制器的postComment()函数访问的表单相关联的正确方法。如果您只为所有表单使用一个模型,那么开始在一个帖子上留下评论将开始对所有表单发表评论 - 除非您使用隐藏的post.id字段执行一些奇怪的操作,但是感到单一。

2 个答案:

答案 0 :(得分:2)

您可以将对象传递给函数调用。

<form ng-submit="postComment(post.id)">

就其他输入而言,它实际上取决于具体情况,但在这种情况下,inputtextarea位于ngRepeat内,这会创建新范围。因此,分配范围上的值不会影响页面上的其他元素。

<li ng-repeat="post in posts">
    <h2>{{post.title}}
    <p>{{post.description}}</p>
    <h3>Leave a comment</h3>
    <form ng-submit="postComment(post.id, commentName, commentText)">
       Name: <input type="text" ng-model="commentName"> <br>
       Comment: <textarea ng-model="commentText"></textarea> <br>
       <input type="submit" value="Post comment">
    </form>
</li>

答案 1 :(得分:1)

  

有没有办法利用那里的双向沟通​​? (例如,在postComment中完成的AJAX调用中添加一个errmsg字段,或者在提交时清除表单?)

我建议使用自己的控制器。使用此方法,comment模型封装在指令中。该指令需要两条信息:1)postID 2)调用保存注释的函数。为了支持显示从服务器返回的错误消息,回调函数与注释一起传递。这允许控制器在保存操作尝试之后向指令提供任何错误消息或其可能需要的任何其他信息。

app.directive('commentForm', function() {
  var template = '<form name="commentForm" '
    + 'ng-submit="save({comment: comment, callbackFn: callbackFn})">'
    + '<h3>Leave a comment</h3>'
    + 'Name: <input type="text" ng-model="comment.name" name="commentName"> <br>'
    + '<span class="error" ng-show="commentForm.commentName.$error.myError">Error</span><br>'
    + 'Comment: <textarea ng-model="comment.text"></textarea> <br>'
    + '<input type="submit" value="Save comment">'
    + '</form>';
  return {
    restrict: 'E',
    template: template,
    scope: { postId: '@', save: '&' },
    controller: function($scope) {
      $scope.callbackFn = function(args) {
        console.log('callback', args);
        if(args.error.name) {
          $scope.commentForm.commentName.$setValidity("myError", false);
        } else {
          // clear form
          $scope.comment.name = '';
          $scope.comment.text = '';
        }
      };
    }
  };
});


app.controller('MainCtrl', function($scope, $timeout) {
  $scope.post = {id: 1};
  $scope.saveComment = function(comment, callbackFn) {
    console.log('saving...', comment);
    // Call $http here... then call the callback.
    // We'll simulate doing something with a timeout.
    $timeout(function() {
      if(comment.name === "name") {
        callbackFn( {error: {name: 'try again'}} );
      } else {
        callbackFn( {error: {}} );
      }
   }, 1500)
  }
});

使用如下:

<comment-form post-id="{{post.id}}" save="saveComment(comment, callbackFn)"></comment-form>

请注意与'&amp;'相关的奇怪语法语法:在HTML中使用该指令时,指定saveComment()函数的参数。在指令/模板中,使用对象/映射将每个参数名称与其值相关联。该值是本地/指令范围属性。

Plnkr。在plnkr中,我使用1.5秒的$ timeout模拟了一个AJAX帖子。如果您在名称文本框中输入name并单击保存按钮,则会在1.5秒内收到错误消息。否则表格会在1.5秒后清除。

根据你想要采取的程度......你也可以将你的帖子模板封装成一个指令:

<li ng-repeat="post in posts">
   <post=post></post>
   <comment-form ...></comment-form>
</li>

您还可以将注释表单放在post指令模板中,进一步简化HTML:

<li ng-repeat="post in posts">
   <post=post></post>
</li>

您还可以使用post-list指令,其模板将包含ng-repeat,将HTML缩减为单个元素:

<post-list posts=posts></post-list>

我个人还没有决定应该使用自定义指令多远。我会对人们对此有任何评论非常感兴趣。