双向绑定,范围变量undefined

时间:2014-07-23 12:19:40

标签: javascript angularjs onsen-ui

我正在使用OnesnUI和AngularJS编写应用程序,使用ng-model从DOM元素中获取输入。

有我的代码

<body>
  <ons-screen>
      <ons-page class="center" ng-controller="page1Ctrl">
    <ons-navigator title="Page 1">
        <div class="center">
          <h1>Pharmy</h1>
            <ons-text-input ng-model="medName" placeholder="Enter Medicine Name" style="display:block; width:100%;" id="test"></ons-text-input>
            <div style="position:relative">
                <ons-text-input ng-model="location" placeholder="Enter Location" style="display:block; width:100%; margin-top:10px;"></ons-text-input>
                <ons-icon icon="search" style="position:absolute;right:10px;top:5px;"></ons-icon>
            </div>
            <ons-button ng-click="goToPage2()"
                        style="width:10%; margin-top:10px;">
                <ons-icon icon="search"></ons-icon>
            </ons-button>
        </div>
    </ons-navigator>
          </ons-page>
  </ons-screen>
</body>

并尝试从输入文本框中检索值,这是我的app.js

    (function () {
        'use strict';
        var app = angular.module('myApp', ['onsen.directives']);
        app.controller('page1Ctrl',['$scope','pageService',function($scope,pageService){
            $scope.$watch('medName',function(newVlaue){
                console.log('Watching YOU !' + newVlaue);
            });
            console.log($scope.medName);
            $scope.goToPage2 = function(){
                console.log('Going to page2 !');
                console.log($scope.medName);
                pageService.start($scope.medName);
                $scope.ons.navigator.pushPage("page2.html");
            }
        }]);
    })();

为什么medName打印值为undefined

4 个答案:

答案 0 :(得分:4)

如果我必须在Angular中命名一个适当的痛苦,那将是范围继承。

如果您让我们说$scope.foo = "hello"是控制器,然后您创建该控制器的子范围,然后您尝试将新值分配给foo,这将创建一个<在新范围内强>新 foo。您的父控制器永远不会看到更改。

在您的问题中,您没有创建新范围,但OnsenUI可能会在ons-screenons-navigator上执行此操作。然后你的输入在一个新的子范围内,如果你试图分配newMed它将在子范围内这样做。

规则始终是拥有对象,称为dot rule(检查here)。

因此,如果您不想再次遇到此问题,请务必按照我在评论中告诉您的内容,创建类似$scope.meds = {}然后ng-model="meds.newMed"的内容,因为这样,它会搜索对于父母的meds,如果它找到它,它将使用它,这就是你想要做的。

这是第一个做错的例子:http://plnkr.co/edit/IJZOa1pXtcQePiEVMzjZ?p=preview

<body ng-controller="MainCtrl">
  <foo>
    <input ng-model="name"> <br />
    Inside new scope: {{ name }}
  </foo>
  <br />
  On the parent scope: {{ name }}

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});

app.directive('foo', function() {
  return {
    restrict: 'E',
    scope: true
  };
});

这里我们是一个创建名为foo的新范围的指令。然后在我们的html上,在<foo>内,我们将ng-modelname放在一起。它读取当前范围,哦,不存在,所以它会进入控制器的范围并找到它。所以你在输入上看到World。当您更改输入时,它将获取其内容并指定新值。怎么样?它到了它的范围,并分配它。问题是它的范围是由foo创建的新范围,因此父母将永远不会看到任何更改。

让我们看一下第二个例子:http://plnkr.co/edit/BSx37PpAEbPnHfs2jr5o?p=preview

<body ng-controller="MainCtrl">
  <foo>
    <input ng-model="user.name"> <br />
    Inside new scope: {{ user.name }}
  </foo>
  <br />
  On the parent scope: {{ user.name }}
</body>

-

app.controller('MainCtrl', function($scope) {
  $scope.user = {
    name: 'World'
  };
});

app.directive('foo', function() {
  return {
    restrict: 'E',
    scope: true
  };
});

这里,相同的例子,但有一个小的改变。这里我们在名为name的对象中有user。当输入读取它时,没有区别,但是当它将 asign 一个新值时,它会做一些不同的事情,例如:嘿,新范围,你有这个用户对象吗? Errr no ...好吧,父母,你有这个用户对象吗?我做。好的,然后用这个内容加入一个名为name的属性。

你看到了区别吗?在它没有问父母之前,它只是在内部范围上创建name,但如果你使用对象,它将首先尝试找到对象,正是我们需要的。

TL; DR; 是:始终使用对象,因为您遇到的一些指令是创建新范围而新的分配是将在内部范围内创建。

答案 1 :(得分:0)

创建了一个简单的jsfiddle来展示它是如何完成的并且在Angular中运行良好。

您的第一个console.log将未定义,因为您尚未在控制器中设置任何内容

这样的东西
 $scope.medName = '';

会有所帮助。

我在示例中用于演示的控制器的代码片段:

function test($scope){
    $scope.medName = '';
    console.log($scope.medName);
    $scope.$watch('medName',function(newValue){
        console.log("new Value:"+newValue);
    });
    $scope.getUpdatedScope = function(){
        console.log($scope.medName);
    }
}

答案 2 :(得分:0)

您的代码实际上有效,您是否在实际输入中键入了内容?它在开头写入undefined,因为它是,它没有在作用域中定义,并且您的输入值为null。

我快速制作了一个jsfiddle,这是(基本上是你的)代码。 HTML:

<div ng-app="myApp">
    <div ng-controller="page1Ctrl">
        <input ng-model="medName" />
        <p ng-if="medName">{{medName}}</p>
    </div>
</div>

JS:

var app = angular.module('myApp', []);
app.controller('page1Ctrl',['$scope', function($scope){
    $scope.$watch('medName',function(newVlaue){
        console.log('Watching YOU !' + newVlaue);
    });
    console.log($scope.medName);
}]);

以下是jsfiddle:http://jsfiddle.net/q3z22/4/ 您将在开头的控制台中看到“未定义”,然后在输入中写入任何内容。如果您不想这样做,只需通过编写$scope.medName = '';来定义范围,并且在开始时您将有一个空字符串。

答案 3 :(得分:0)

您是否在某处设置了ng-app指令?尝试将其添加到body标签中,如下所示:

<body ng-app="myApp">