当我把ng-controller放在div而不是body autocomplete停止工作时

时间:2015-02-08 17:55:22

标签: angularjs angularjs-scope angular-ui

我有一个具有自动填充功能的文本框,点击“单击我”按钮后,自动填充中的文字将添加到表中,这里的链接完全正常,

 var app = angular.module('app', []);
app.factory('Service', function() {
    var typesHash = [ {
        id :1,
        name : 'lemon',
        price : 100,
        unit : 2.5
    }, {
        id : 2,
        name : 'meat',
        price : 200,
        unit : 3.3
    } ];

    var localId = 3;
    availableTags = [
                      "ActionScript",
                      "AppleScript",
                      "Asp",
                      "BASIC",
                      "C",
                      "C++",
                      "Clojure",
                      "COBOL",
                      "ColdFusion",
                      "Erlang",
                      "Fortran",
                      "Groovy",
                      "Haskell",
                      "Java",
                      "JavaScript",
                      "Lisp",
                      "Perl",
                      "PHP",
                      "Python",
                      "Ruby",
                      "Scala",
                      "Scheme"
                    ];
    var service = {
        addTable : addTable,
        getData : getData,
        complete:complete


    };
    return service;
    function complete($scope){
        $( "#txt" ).autocomplete({
          source: availableTags,
          messages: {
              noResults: '',
              results: function() {}
          }
        });
        $("#txt" ).on( "autocompleteselect", function( event, ui ) {
         $scope.tableTools.inputData=ui.item.value;
        } );
        } 
    function addTable(name,price) {
        typesHash.push({id:localId++, name:name, price:price,unit:1});
    }
    function getData() {
        return typesHash;
    }
});
app.controller('table', function(Service,$scope) {
    //get the return data from getData funtion in factory
    this.typesHash = Service.getData();
    //get the addtable function from factory 
    this.addTable = Service.addTable;
    this.complete=Service.complete($scope);
});

working link

但是只要我把ng-controller =“table as tableTools”放在div而不是body中,然后自动填充文本框开始表现得很有趣并且它无法正常工作

not working link

任何人都可以解释原因并告诉我如何以一种方式修复它,即使将ng-controller =“table as tableTools”放在div中也可以吗?

更新

这是错误:

未捕获的TypeError:无法设置未定义的属性'inputData'

这一行:

$scope.tableTools.inputData = ui.item.value;

(请记住点击建议的文字后问题就开始了)

3 个答案:

答案 0 :(得分:2)

这种情况正在发生,因为您在同一页面上有两个带有两个不同元素的控制器,因此范围没有正确绑定。

您执行此操作的最佳代码是: -

<html>

  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <script src="//code.jquery.com/jquery-1.10.2.js"></script>
  <script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
    <link data-require="bootstrap@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
     <link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">

    <title>Insert title here</title>
    <script>
    var app = angular.module('app', []);
    app.factory('Service', function() {
        var typesHash = [ {
            id :1,
            name : 'lemon',
            price : 100,
            unit : 2.5
        }, {
            id : 2,
            name : 'meat',
            price : 200,
            unit : 3.3
        } ];

        var localId = 3;
        availableTags = [
                          "ActionScript",
                          "AppleScript",
                          "Asp",
                          "BASIC",
                          "C",
                          "C++",
                          "Clojure",
                          "COBOL",
                          "ColdFusion",
                          "Erlang",
                          "Fortran",
                          "Groovy",
                          "Haskell",
                          "Java",
                          "JavaScript",
                          "Lisp",
                          "Perl",
                          "PHP",
                          "Python",
                          "Ruby",
                          "Scala",
                          "Scheme"
                        ];
        var service = {
            addTable : addTable,
            getData : getData,
            complete:complete


        };
        return service;
        function complete($scope){
            $( "#txt" ).autocomplete({
              source: availableTags,
              messages: {
                  noResults: '',
                  results: function() {}
              }
            });
            $("#txt" ).on( "autocompleteselect", function( event, ui ) {
              console.log($scope);
             $scope.tableTools.inputData=ui.item.value;
            } );
            } 
        function addTable(name,price) {
            typesHash.push({id:localId++, name:name, price:price,unit:1});
        }
        function getData() {
            return typesHash;
        }
    });
    app.controller('table', function(Service,$scope) {
        //get the return data from getData funtion in factory
        this.typesHash = Service.getData();
        //get the addtable function from factory 
        this.addTable = Service.addTable;
        this.complete=Service.complete($scope);
    });
    </script>
  </head>

  <body ng-app="app" ng-controller="table as tableTools" >
    <form >
      <div class="row commonRow"  >
        <div class="col-xs-1 text-right">
          item:
        </div>
        <div class="col-xs-5">
         <input id="txt" type="text" style="width: 100%;" ng-keyup="tableTools.complete()" ng-model="tableTools.inputData">
        </div>
        <div class="col-xs-2">
          <button class="btn btn-primary" ng-click="tableTools.addTable(tableTools.inputData);tableTools.inputData=''">
                click me
              </button>
        </div>
      </div>  
    </form>

    <div class="row commonRow">
      <div class="col-xs-1"></div>
      <div class="col-xs-10">
        <table class="table table-hover">
          <thead>
            <tr>
              <th>item</th>
            </tr>
          </thead>
          <tbody> <!--No need for controller here-->
            <tr ng-repeat="x in tableTools.typesHash track by x.id">
              <td>
                <div>{{x.name}}</div>
              </td>

            </tr>
          </tbody>
        </table>
      </div>
    </div>
  </body>

</html>

Plunker

答案 1 :(得分:1)

如果你添加

$scope.tableTools={}

正下方

function complete($scope){

第二个按预期工作。

  

任何人都可以解释原因

只要尚未定义对象'$ scope.tableTools',就无法成功向其添加属性

答案 2 :(得分:1)

这个问题隐藏在对angularjs对象生命周期的误解中。

最重要的是:

  • services (工厂/提供商...不同的创作,但最后相同) 单身
  • 每个视图
  • controllers 实例化(通过角度应用程序生命周期,有一个控制器有很多,多个实例..)

那发生了什么?

有一项服务:

app.factory('Service', function() {
   ...

并且有一个控制器将其范围传递到该服务

app.controller('table', function(Service,$scope) {
    ...
    this.complete=Service.complete($scope);

在页面上我们可以看到:

// first usage of controller
// its first instance is created, $scope is passed
<div class="row commonRow" ng-controller="table as tableTools">

// second usage
// different instance is created... and it also passes the §scope
<tbody ng-controller="table as iterateTb">

但如上所述 - 服务只有一个。当第一个控制器通过其$scope时,第二个控制器也会在...之后执行..这导致了问题。

我们可以使用控制器内部的服务。这是角度的设计原则。但我们不应该通过美元范围......