Newbie AngularJS Controller $ scope无法读取undef的属性

时间:2016-12-06 06:58:43

标签: angularjs controller angularjs-scope

我试图解决一个问题,显然有些新手有时会有Angular经验。即使有几个帖子我也没有发现我的小例子的问题。情形:

  • 显示评论的网页&评分。
  • 该网站提供了输入新评论/评级的可能性
  • javascript应该将新条目推送到现有注释数组
  • 整个故事中很容易有一个控制器,但是有意了解“继承”。控制器的模型,因此有两个小控制器

问题:

  • 将新条目推送到数组的函数(在controller2中) 现有注释(控制器1)会导致TypeError,因为此范围内的数组未定义。



'use strict';

angular.module('confusionApp', [])

        .controller('DataController', ['$scope', function($scope) {
            $scope.comments = [{rating: 1, comment:"bla", author: "pma", date: new Date().toISOString()} , {rating:2, comment:"harakiri", author:"hku", date: new Date().toISOString()}];
        }])

        .controller('CommentController', ['$scope', function($scope) {

            $scope.comment = {rating:5, comment:"", author:"", date: new Date().toISOString() };

            $scope.submitComment = function () {
                console.log($scope.comment);
                $scope.comment.date = new Date().toISOString();

                // this scope here does not know about the comments array --> BUG                
                $scope.comments.push($scope.comment);
                $scope.commentForm.$setPristine();
                $scope.comment = {rating:5, comment:"", author:"", date: new Date().toISOString()};
                console.log($scope.comment);
            };
        }])

;




HTML页面



<!DOCTYPE html>
<html lang="en" ng-app="confusionApp">

<head>
     <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head
         content must come *after* these tags -->
    <title>Ristorante Con Fusion: Menu</title>
        <!-- Bootstrap -->
<!-- build:css styles/main.css -->
    <link href="../bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="../bower_components/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet">
    <link href="../bower_components/font-awesome/css/font-awesome.min.css" rel="stylesheet">
    <link href="styles/bootstrap-social.css" rel="stylesheet">
    <link href="styles/mystyles.css" rel="stylesheet">
<!-- endbuild -->

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
</head>

<body>
    <div class="container">
        <div class="row row-content">
            <div class="col-xs-12">
              <div class="row row-content" ng-controller="DataController">
                  <div class="col-xs-9 col-xs-offset-1">
                      <blockquote ng-repeat="comment in comments | orderBy: sortOption">
                        <p>{{comment.rating}} Stars</p>
                        <p>{{comment.comment}}</p>
                        <footer>{{comment.author}}, {{comment.date | date}}</footer>
                      </blockquote>
                  </div>
            </div>
            <div class="col-xs-9 col-xs-offset-1" ng-controller="CommentController">
                <form class="form-horizontal" name="commentForm" ng-submit="submitComment()" novalidate>
                  <!-- name property -->
                  <div class="form-group" ng-class="{ 'has-error' : commentForm.author.$error.required || commentForm.author.$pristine }">
                      <label for="name" class="col-sm-2 control-label">Name</label>
                      <div class="col-sm-10">
                        <input type="text" class="form-control" id="author" name="author" placeholder="Enter your name" ng-model="comment.author" required>
                        <span ng-show="commentForm.author.$error.required || commentForm.author.$pristine" class="help-block">Your name is required</span>
                      </div>
                  </div>
                  <!-- the rating -->
                  <div class="form-group">
                    <label for="rating" class="col-sm-2 control-label">Rating</label>
                    <div class="col-sm-10">
                      <label class="radio-inline">
                          <input type="radio" name="ratingGroup" id="inlineRadio1" ng-model="comment.rating" value="1"> 1
                      </label>
                      <label class="radio-inline">
                          <input type="radio" name="ratingGroup" id="inlineRadio1" ng-model="comment.rating" value="2"> 2
                      </label>
                      <label class="radio-inline">
                          <input type="radio" name="ratingGroup" id="inlineRadio1" ng-model="comment.rating" value="3"> 3
                      </label>
                      <label class="radio-inline">
                          <input type="radio" name="ratingGroup" id="inlineRadio1" ng-model="comment.rating" value="4"> 4
                      </label>
                      <label class="radio-inline">
                          <input type="radio" name="ratingGroup" id="inlineRadio1" ng-model="comment.rating" value="5"> 5
                      </label>
                    </div>
                  </div>
                  <!-- the comments -->
                  <div class="form-group" ng-class="{ 'has-error' : commentForm.comment.$error.required || commentForm.comment.$pristine }">
                      <label for="feedback" class="col-sm-2 control-label">Your Comment</label>
                      <div class="col-sm-10">
                          <textarea class="form-control" id="comment" name="comment" rows="12" ng-model="comment.comment" placeholder="Please provide some comments" required></textarea>
                          <span ng-show="commentForm.comment.$error.required || commentForm.comment.$pristine" class="help-block">Your comment is required !</span>
                      </div>
                  </div>
                  <!-- the button -->
                  <div class="form-group">
                      <div class="col-sm-offset-2 col-sm-10">
                          <button type="submit" class="btn btn-primary" ng-disabled="commentForm.$invalid">Send Comments</button>
                      </div>
                  </div>
                </form>
            </div>
        </div>
    </div>

<!-- build:js scripts/main.js -->
    <script src="../bower_components/angular/angular.min.js"></script>
    <script src="scripts/app.js"></script>
<!-- endbuild -->

</body>

</html>
&#13;
&#13;
&#13;

谢谢,任何暗示都会受到赞赏。

2 个答案:

答案 0 :(得分:1)

通常,每个视图一个控制器。在同一视图中有两个控制器:DataController和CommentController。

数组应存储在Service中(在两个控制器中注入; CommentController向服务的数组添加注释; DataController从中读取)。

当ng-click(CommentController)触发通常应刷新DataController中使用的数组的事件时,事情变得复杂。

正确的方法是只使用一个控制器。

以下是我为数组设置服务的方法:

.service('CommentService', function() {
  var comments = [
    {rating: 1, comment:"bla", author: "pma", date: new Date()}, 
    {rating:2, comment:"harakiri", author:"hku", date: new Date()}
  ];

  return {
    comments: comments
  }
})

http://codepen.io/nadeemramsing/pen/QGmzbV?editors=1111
(解决方案虽然不完整;只需使用一个控制器)

答案 1 :(得分:1)

您想了解继承控制器范围。你的例子中出错的地方是CommentController实际上并不是DataController的子控制器,因此不会继承范围。

因此,您需要确保在HTML中DataController是CommentController的父级。实现此目的的简单方法是将DataController移动到body元素:

<body ng-controller="DataController">