when I put ng-controller in div instead of body autocomplete stops working

 ̄綄美尐妖づ 提交于 2019-12-06 20:05:29

The issue is hidden in missunderstanding of the angularjs object life-cycles.

The most important here to know is:

  • services (factory/provider ... different creation, but at the end the same) are singletons
  • controllers are instantiated per each view. (There are many, multi instances of one controller through the angular app life time..)

So what happened?

There is one service:

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

and there is one controller passing its scope into that service

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

And on the page we can see:

// 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">

But as described above - service is only one. While first controller passes its $scope, the second does after while as well.. and that is causing the issue.

We can use services inside of controllers. That is the design principle of angular. But we should not pass the $scope...

This is happening because you have two controller on the same page with two differenct element therefore scope is not binding properly.

The best code for you to do this is :-

<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

If you add

$scope.tableTools={}

right below

function complete($scope){

the second one works as expected.

can anyone explain the reason

As long as the object ‘$scope.tableTools‘ has not been defined, you cannot successfully add attributes to it

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!