NG模型不会更新控制器值


270

可能是愚蠢的问题,但是我的html表单带有简单的输入和按钮:

<input type="text" ng-model="searchText" />
<button ng-click="check()">Check!</button>
{{ searchText }}

然后在控制器中(从routeProvider调用模板和控制器):

$scope.check = function () {
    console.log($scope.searchText);
}

为什么单击按钮后,视图在控制台中正确更新但未定义?

谢谢!

更新:似乎我实际上已经解决了该问题(之前不得不提出一些解决方法),方法是:只需将我的属性名称从更改searchTextsearch.text,然后$scope.search = {};在控制器中定义空对象,瞧……不知道为什么它起作用虽然;]


您确定在文档的此部分中正在使用此控制器吗?您可以张贴一个最小的失败示例吗?
wroniasty

1
是的,100%确定控制器正常,这个问题对我来说似乎很熟悉...令人惊讶的是,当我将属性名称从更改为时,它起作用searchTextsearch.text,知道为什么吗?
炼金术2012年

4
@Arthur:这不太明显,但是ng-model仅在您的视图中创建一种说话的局部变量,因此,如果要保持这种方式,则需要将其传递到check()函数,例如:check( searchText),然后您的控制器会识别出它。希望能
有所

3
根据记录,它的拼写voila,不vualawolla等等
丹Bechard

3
我认为您正在寻找的答案在stackoverflow.com/a/14049482/1217913
Willa 2015年

Answers:


71

控制器作为版本(推荐)

这里的模板

<div ng-app="example" ng-controller="myController as $ctrl">
    <input type="text" ng-model="$ctrl.searchText" />
    <button ng-click="$ctrl.check()">Check!</button>
    {{ $ctrl.searchText }}
</div>

JS

angular.module('example', [])
  .controller('myController', function() {
    var vm = this;
    vm.check = function () {
      console.log(vm.searchText);
    };
  });

例如:http//codepen.io/Damax/pen/rjawoO

最好是使用Angular 2.x或Angular 1.5或更高版本的组件

########

方法(不推荐)

不建议这样做,因为字符串是原始的,强烈建议使用对象代替

在标记中尝试这个

<input type="text" ng-model="searchText" />
<button ng-click="check(searchText)">Check!</button>
{{ searchText }}

这在您的控制器中

$scope.check = function (searchText) {
    console.log(searchText);
}

17
这仅适用于单向操作...如果要更改值,该searchText怎么办?
cdmckay

199
这也没有回答“为什么?” 题。
cdmckay

4
如果我不想使用任何按钮怎么办?例如,我需要在Enter上提交
danikoren

2
Saniko =>要在Enter上提交,您必须在它上面使用表单标签和ng-submit(docs.angularjs.org/api/ng.directive:ngSubmit
Damax 2014年

1
@ HP's411这是因为字符串是基元。当Angular分配值时,它将指针更改为该值,因此控制器会查看旧值,因为它具有指向该值的旧指针。
Damax

620

“如果使用ng-model,则必须在其中有一个点。”
将您的模型指向一个object.property,您将可以正常使用。

控制者

$scope.formData = {};
$scope.check = function () {
  console.log($scope.formData.searchText.$modelValue); //works
}

模板

<input ng-model="formData.searchText"/>
<button ng-click="check()">Check!</button>

当子级示波器在起作用时(例如子级路由或ng-repeats)会发生这种情况。子作用域创建了它自己的值,并且产生了名称冲突,如下所示

观看此视频片段以了解更多信息:https : //www.youtube.com/watch?v=SBwoFkRjZvE&t=3m15s


94
这是真正的答案。
凯斯勒2014年

16
@Catfish通过原型继承,无论何时写入子属性,对父属性的引用/连接都将不复存在。如果您没有点,则Angular Scopes建模的方式将在子范围内创建一个新属性。该视频对其进行了更详细的说明:youtube.com/watch?
Will Stern

1
格拉西亚斯老板。这是真的!但是,这似乎并不是一个一致的怪癖,因为我仅在与Ionic框架一起使用时才遇到问题
Don Barry

6
@ user3677331它可以正常工作,没有点号,直到您有一个尝试与其对话的子范围(例如ng-repeat中的项)为止。假设您的模型名称是“ phone”,那么您的子范围将创建“ phone”,那么您将遇到范围冲突,因为child-scope具有“ phone”变量,因此无法在父范围上访问“ phone”。而如果子范围创建了user.phone,它将被添加到父范围的用户对象中,因此两个范围都指向同一个对象
Will Stern

3
很有帮助。我不确定我是否能找到一个相对模糊的问题的答案,但这一直没有解决。
CodeManiak

57

在《用AngularJS掌握Web应用程序开发》一书第19页中写道:

避免直接绑定到范围的属性。双向数据绑定到对象的属性(在作用域上公开)是一种首选方法。根据经验,在提供给ng-model指令的表达式中应该有一个点(例如ng-model =“ thing.name”)。

范围只是JavaScript对象,它们模仿dom层次结构。根据JavaScript Prototype Inheritance,作用域属性通过作用域分开。为避免这种情况,应使用点表示法来绑定ng模型。


2
感谢您的参考。我认为这与ng-model有关。
国王

44

使用this代替$scope工程。

function AppCtrl($scope){
  $scope.searchText = "";
  $scope.check = function () {
    console.log("You typed '" + this.searchText + "'"); // used 'this' instead of $scope
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app>
  <div ng-controller="AppCtrl">
    <input ng-model="searchText"/>
    <button ng-click="check()">Write console log</button>
  </div>
</div>

编辑:在编写此答案时,我的情况要复杂得多。发表评论后,我尝试重现它以了解它为什么起作用,但是没有运气。我认为以某种方式(实际上不知道为什么)生成了一个新的子范围并this引用了该范围。但是如果$scope使用,由于javascript的词法作用域功能,它实际上是指向父$ scope 。

如果有人遇到此问题,以这种方式进行测试并通知我们,那就太好了。


完美无瑕,你真是个天才
fjcero

1
似乎附加的函数$scope创建了一个新的作用域(即function中check()this是指的子作用域的作用域$scope)。为什么会这样呢?你能给一些解释吗?
杨勋

1
在这种情况下,为什么要使用“ this”而不是“ $ scope”?因为它在我先前的项目中使用$ scope可以工作,但是这次同样的事情在$ scope下不起作用。但是“这个”已经奏效了。这是为什么?
Rashedul.Rubel

这行得通,但是如果您说this.searchText = "something else",甚至$scope.searchText = "something else",它也不会更新视图。你能解释这个问题吗?
Shri

这应该。我使用上面的代码尝试过,它更新了视图。
Feyyaz

13

我遇到了同样的问题,这是由于我没有在控制器顶部首先声明空白对象:

$scope.model = {}

<input ng-model="model.firstProperty">

希望这对您有用!


10

在处理非平凡的视图(存在嵌套作用域)时,我遇到了相同的问题。最终发现由于基于原型的Java脚本继承的性质,这在开发AngularJS应用程序时是一件棘手的事情。AngularJS嵌套作用域是通过这种机制创建的。并且从ng-model创建的值放在子级作用域中,并不是说父级作用域(也许是注入控制器的那个)不会看到该值,如果不使用点,该值还将隐藏父级作用域中定义的具有相同名称的任何属性强制执行原型参考访问。有关更多详细信息,请查看专门用于说明此问题的在线视频,http://egghead.io/video/angularjs-the-dot/及其后续评论。


6

看看这个小提琴 http://jsfiddle.net/ganarajpr/MSjqL/

我(我想是!)完全完成了您的工作,而且似乎正在工作。您可以检查哪些不适用于您吗?


嗯..谢谢您的研究,我想它应该可以工作...为什么它对我不起作用?还有更重要的一点:为什么它适用于对象而不适用于普通字符串变量?也许是因为我在routeProvider中以不适当的方式引用了我的控制器?试图避免全局变量,并将我的控制器作为modulename.ctrlName放入controllers.js文件中。会引起头痛吗?
炼金术2012年

我不太确定为什么它对您不起作用。如果您可以将这个问题
弄得一团糟

好吧,会的,现在就完成工作,但是肯定会在明天或傍晚做,干杯!我为ctrl命名空间的方式可能有问题,我们将看到...
炼金术2012年

6

由于没有人提到这一问题,可以通过添加$parent到bound属性来解决该问题

<div ng-controller="LoginController">
    <input type="text" name="login" class="form-control" ng-model="$parent.ssn" ng-pattern="/\d{6,8}-\d{4}|\d{10,12}/" ng-required="true" />
    <button class="button-big" type="submit" ng-click="BankLogin()" ng-disabled="!bankidForm.login.$valid">Logga in</button>
</div>

和控制器

app.controller("LoginController", ['$scope', function ($scope) {
    $scope.ssn = '';

    $scope.BankLogin = function () {
        console.log($scope.ssn); // works!
    };
}]);

感谢您的回答,但是y在起作用吗?理想情况下,它应该在同一个作用域元素上工作,而不是在父元素上工作?
V31

5

对我来说,问题是通过将数据存储到一个对象(这里是“数据”)中而解决的。

NgApp.controller('MyController', function($scope) {

   $scope.my_title = ""; // This don't work in ng-click function called

   $scope.datas = {
      'my_title' : "",
   };

   $scope.doAction = function() {
         console.log($scope.my_title); // bad value
         console.log($scope.datas.my_title); // Good Value binded by'ng-model'
   }
   

});

我希望这会有所帮助


3
这里的话题很少,但是“数据”是“基准”的复数形式
thethakuri

@thethakuri和匈牙利语中的“基准”是“日期”,因此我肯定不会使用:P
EpicPandaForce

我更喜欢华夫饼屋,而不是IHOP
Nico Westerdale

2

我使用绑定到body-element的root_controller遇到了这个问题。然后我在角路由器上使用了ng-view。问题在于,当将html插入ng-view元素时,angular ALWAYS始终会创建新的作用域。因此,我的“检查”功能是在由ng-model元素修改的作用域的父作用域上定义的。

要解决此问题,只需在路由加载的html内容中使用专用控制器即可。


2

您可以执行以下操作以在ng-keypress输入中输入文本和在ng-click图标中启用搜索:

<input type="text" ng-model="searchText" ng-keypress="keyEnter(this,$event)" />
<button ng-click="check(searchText)">Check!</button>

in the controller
$scope.search = function (searchText) {
        console.log(searchText);
    }
    $scope.keyEnter = function (serachText,$event) {
        var keyCode = $event.which || $event.keyCode;
        if (keyCode === 13) {//KeyCode for Enter key
           console.log(searchText);
        }
    }

2

我有同样的问题。
正确的方法是将“ searchText”设置为对象内部的属性。

但是,如果我想按原样保留字符串,该怎么办?好吧,我尝试了这里提到的每种方法,但没有任何效果。
但是后来我注意到问题仅在于初始化,因此我只设置了value属性就可以了。

<input type="text" ng-model="searchText" value={{searchText}} />

这样,将值设置为“ $ scope.searchText”值,并在输入值更改时进行更新。

我知道这是一种解决方法,但对我有用。


2

我遇到了同样的问题。对我有效的解决方法是使用此关键字.......。

警报(this.ModelName);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.