web-dev-qa-db-ja.com

Ng-modelはコントローラーの値を更新しません

おそらくばかげた質問ですが、私は単純な入力とボタンで私のHTMLフォームを持っています:

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

次に、コントローラ内で(テンプレートとコントローラはrouteProviderから呼び出されます):

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

ボタンをクリックしたときに、コンソールでビューが正しく更新されたが未定義になるのはなぜですか。

ありがとうございます。

更新日:私は実際にその問題を(いくつかの回避策を考え出す必要がありました)解決したように思えます:searchTextからsearch.textに変更し、それから空の$scope.search = {};オブジェクトをコントローラに定義してください。なぜそれがうまくいっているのか。

262
alchemication

バージョンのコントローラ(推奨)

ここにテンプレート

<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);
}
70
Damax

「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

596
Will Stern

AngularJSを使ったWebアプリケーション開発の習得の本p.19では、次のように書かれています。

スコープのプロパティに直接バインドしないでください。 (スコープに公開されている)オブジェクトのプロパティへの双方向データバインディングは、推奨されるアプローチです。経験則として、ng-modelディレクティブに提供される式にドットを含める必要があります(たとえば、ng-model = "thing.name")。

スコープはJavaScriptオブジェクトであり、DOM階層を模倣しています。 JavaScriptプロトタイプの継承 によると、スコープのプロパティはスコープによって分離されています。これを回避するには、ドット表記を使用してng-modelsをバインドする必要があります。

56
efirat

$scopeの代わりにthisを使用するとうまくいきます。

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の 字句スコープ の機能により、実際は親の$スコープを参照します。

この問題を抱えている人がこの方法でテストして私たちに知らせてくれたら素晴らしいでしょう。

42
Feyyaz

私は同じ問題を抱えていました、そしてそれは私が私のコントローラーの一番上で最初に空白のオブジェクトを宣言しなかったことが原因でした:

$scope.model = {}

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

これがあなたのために働くことを願っています!

10
Millsionaire

自明ではないビューを扱うときに同じ問題に遭遇しました(スコープがネストされています)。そして最後に、Javaスクリプトのプロトタイプベースの継承の性質により、AngularJSアプリケーションを開発するときにこれが既知の注意が必要なことであることがわかりました。 AngularJSのネストされたスコープはこのメカニズムを通して作成されます。そして、ng-modelから生成された値は、親スコープ(おそらくコントローラに注入されたもの)が値を見ないということではなく、子スコープに置かれます。プロトタイプ参照アクセスを強制するため。詳細については、この問題を説明するためのオンラインビデオをご覧ください。 http://egghead.io/video/angularjs-the-dot/ およびコメントフォローアップ.

9
Roger Jin

このフィドルを見てください http://jsfiddle.net/ganarajpr/MSjqL/

私はあなたがしていたことと全く同じことをしました(そして私は仮定します)そしてそれは働いているようです。ここで何が機能していないのかを確認できますか。

5
ganaraj

私にとっては、データはオブジェクト(ここでは "datas")に格納することで解決しました。

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'
   }
   

});

私はそれをホップします

4
Plici Stéphane

誰もこれに言及していないので、バウンドプロパティに$parentを追加することで問題を解決することができます

<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!
    };
}]);
4
Eric Herlitz

私はちょうどbody-elementにバインドされたroot_controllerを使用してこのまさしく問題を抱えていました。それから私は角度ルーターでng-viewを使っていました。問題は、ng-view要素にhtmlを挿入すると、角度付きのALWAYSが新しいスコープを作成することです。結果として、私の "check"関数は私のng-model要素によって修正されたスコープの親スコープで定義されました。

この問題を解決するには、ルートロードされたHTMLコンテンツ内で専用のコントローラを使用するだけです。

1
moritz

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);
        }
    }
1
Naoufal Gaffa

私は同じ問題に直面していた...私のために働いた解決策は、このキーワードを使用することです..........

alert(this.ModelName);

1
SnktJavaMaster

私は同じ問題を抱えていました。
正しい方法は、 'searchText'をオブジェクト内のプロパティに設定することです。

しかし、そのままにしておきたい場合は、どうなりますか。まあ、私はここで言及したすべての方法を試してみました、何もうまくいきませんでした。
しかし、私は、問題は初期段階にあることに気付いたので、value属性を設定しただけでうまくいきました。

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

このようにして、値は '$ scope.searchText'値に設定され、入力値が変わると更新されます。

私はそれが回避策であることを知っています、しかしそれは私のために働きました..

1
Hike Nalbandyan