AngularJS で「ng-model」を使用する方法と例

⚡ スマートサマリー

AngularJS の ng-model は入力コントロールを $scope のプロパティに直接バインドします。ping ビューとモデルは双方向で同期されます。以下のセクションでは、属性、3つの実例、および初心者が最も陥りやすいエラーについて説明します。

  • 🔗 双方向製本: ng-modelは、ユーザー入力を$scopeプロパティにプッシュし、コントローラーの変更を自動的にコントロールに反映させます。
  • 📝 テキストエリアのバインディング: 複数行の文字列をテキストエリアにバインドし、\n エスケープシーケンスを使用して、レンダリングされた値に強制的に改行を挿入します。
  • ☑️ チェックボックスの状態: ng-modelでバインドされたチェックボックスはブール値を格納するため、trueの場合はチェックボックスがチェックされた状態になり、falseの場合はチェックされていない状態になります。
  • ???? ドロップダウンリスト: select要素にng-optionsを設定し、選択された項目を別のモデルプロパティにバインドします。
  • ⚠️ よくある失敗: セレクトボックスを、そのオプションテキストを提供するオブジェクトと同じオブジェクトにバインドすると、最初の選択時にそのオブジェクトが上書きされます。
  • 🛠️ 検証フック: ng-model は、条件付きスタイルとフォームチェックを駆動する ng-pristine、ng-dirty、ng-valid、および ng-invalid クラスを追加します。

AngularJS の ng-model とは何ですか?

ng-model は AngularJS のディレクティブで、モデルを表し、その主な目的は「ビュー」を「モデル」にバインドすることです。ユーザーがコントロールに入力したものはすべて、プロパティに直接書き込まれます。 $scopeそして、コントローラーがそのプロパティに書き込んだ内容はすべて、そのままコントロールに反映されます。

例えば、エンドユーザーに以下のようなシンプルなページを表示し、テキストボックスに「名」と「姓」を入力するように求めるとします。そして、ユーザーが入力した情報をデータモデルに保存したいとします。

ng-modelディレクティブを使用すると、「名」と「姓」のテキストボックスフィールドをデータモデルにマッピングできます。このディレクティブにより、イベント処理コードを一切記述することなく、「ビュー」と「モデル」のデータが常に同期された状態に保たれます。

⚠️ バージョンに関する注記: AngularJS(1.x ブランチ)は 2021 年 12 月 31 日にサポートが終了し、セキュリティ パッチは提供されなくなりました。以下の例はまだ動作しますが、最新の Angular では同じ双方向バインディングは次のように記述されます。 [(ngModel)] また、FormsModuleが必要です。

ng-model 属性

前述のセクションで説明したように、ng-model属性は、モデル内のデータをユーザーに表示されるビューにバインドするために使用されます。

ng-model 属性は次の目的で使用されます。

  1. ビュー内の入力、テキストエリア、選択要素などのコントロールをモデルにバインドします。
  2. 検証動作を提供する ― 例えば、テキストボックスに検証を追加して、数字のみを入力できるようにすることができる。
  3. コントロールの状態を維持する。ここでいう状態とは、コントロールとデータが常に同期している状態を指します。つまり、データの値が変更されると、コントロールの値も自動的に変更され、その逆も同様です。
  4. その状態をCSSクラスとして公開します。AngularJSは ng-pristine, ng-dirty, ng-valid (NAIST) と ng-invalid ng-model を持つすべてのコントロールに対して、これによりフォームの条件付きスタイル設定が簡単になります。

属性を理解したら、次のステップは、最も頻繁に遭遇する3種類のコントロールタイプにその属性を適用することです。

ngモデルの使い方

1) テキストエリア

テキスト領域タグは、複数行のテキスト入力コントロールを定義するために使用されます。 テキスト領域には無制限の文字数を含めることができ、テキストは固定幅フォントで表示されます。

それでは、テキストエリアコントロールにng-modelディレクティブを追加する簡単な例を見ていきましょう。この例では、コントローラーからビューに複数行の文字列を渡し、その値をテキストエリアコントロールに紐付ける方法を示します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        <textarea rows="4" cols="50" ng-model="pDescription"></textarea>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pDescription = "This topic looks at how Angular JS works \nModels in Angular JS";
    });
</script>
</body>
</html>

Code 説明:

  1. その ng-model ディレクティブ 「p」という名前のメンバ変数を添付しますDescript「テキストエリア」コントロールに「ion」を追加します。「p」Description」変数には、テキストエリアコントロールに渡されるテキストが格納されます。 rows="4" (NAIST) と cols="50" 属性は、複数行のテキストが適切に表示されるようにコントロールのサイズを調整するだけです。
  2. メンバー変数「p」Description”には複数行の値が割り当てられます。 \n 文字列内のエスケープシーケンスによって、テキストエリアがテキストを表示する際に、テキストが強制的に2行目に移動するようになります。

出力:

出力から、コントローラで割り当てられた複数行テキストがテキストエリアコントロールに表示され、正確に2行に分割されていることがわかります。 \n 座ります。

2) 入力要素

ng-model ディレクティブは、通常の入力要素でも機能します。以下では、テキストボックスと 2 つのチェックボックスを同時にバインドすることで、ng-model が文字列値とブール値をどのように並べて処理するかを示します。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pname"><br>
        Topic :<br>
        <input type="checkbox" ng-model="Topic.Controller">Controller<br>
        <input type="checkbox" ng-model="Topic.Models">Models
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pname = "Guru99";

        $scope.Topic = {
            Controller: true,
            Models: false
        };
    });
</script>
</body>
</html>

Code 説明:

  1. ng-model ディレクティブはメンバー変数「pname」をテキスト入力コントロールにアタッチし、プロパティ Topic.Controller (NAIST) と Topic.Models 2つのチェックボックスコントロールへ。
  2. コントローラーでは、「pname」に文字列「Guru99」であり、「Topic」オブジェクトには2つのブール型メンバーが与えられます。ng-modelにバインドされたチェックボックスは常にブール値を読み書きするため、 true ボックスをチェック済みとして表示し、 false 明確にする。

出力:

出力から、

  • 割り当てられた値は pname 変数は「Guru99。 "
  • 最初の境界値は trueチェックボックスは「コントローラー」チェックボックスにマークされています。同様に、2 番目の値は false「モデル」チェックボックスにチェックが入っていません。

3) ドロップダウンから要素を選択します

ng-modelディレクティブはselect要素にも適用でき、ユーザーが選択した項目をモデルに保存することができます。

ここでは、名前を保持するテキスト入力があります。Guru「99」と、「コントローラー」と「モデル」という2つのリスト項目を含む選択リスト。

⚠️訂正: 上記のスクリーンショットは、select要素を同じ要素にバインドした元のリストを示しています。 Topics オプションテキストを提供するオブジェクト。ユーザーがオプションを選択した瞬間、AngularJS がそれを上書きします。 Topics 選択された文字列を使用すると、両方のオプションが消えます。以下の修正されたリストでは、リストを 1 つのプロパティに、選択を別のプロパティに保持し、 ng-options リストを作成する。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Event Registration</title>
    <script src="https://code.angularjs.org/1.8.3/angular.js"></script>
</head>
<body>
<h1>Guru99 Global Event</h1>

<div ng-app="DemoApp" ng-controller="DemoCtrl">
    <form>
        Topic Description:<br><br>
        Name : <input type="text" ng-model="pName"><br>
        Topic :<br>
        <!-- Topics holds the list; selectedTopic holds the choice -->
        <select ng-model="selectedTopic" ng-options="t for t in Topics"></select>
    </form>
</div>

<script>
    var app = angular.module('DemoApp', []);
    app.controller('DemoCtrl', function($scope) {
        $scope.pName = "Guru99";

        $scope.Topics = ["Controller", "Models"];
        $scope.selectedTopic = $scope.Topics[0];
    });
</script>
</body>
</html>

Code 説明:

  1. テキスト入力はバインドされています pName、そして選択要素は selectedTopicセレクトボックスには独自のモデルプロパティがあるため、オプションを選択してもリスト自体が変更されることはありません。
  2. その Topics 配列には「Controller」と「Models」の2つの値が格納されます。 ng-options この式は配列を走査し、エントリごとに1つのオプションを表示するため、3つ目のトピックを追加してもマークアップを変更する必要はありません。
  3. selectedTopic 最初の項目があらかじめ設定されているため、ドロップダウンリストが空白行ではなく、適切なデフォルト値で開きます。

出力:

出力から、割り当てられた値は pName 変数は「Guru99」と表示され、選択コントロールには「コントローラー」と「モデル」のオプションが表示されます。動作例はさておき、バインディングが更新されない場合もあり、その理由を知っておくことは重要です。

ng-modelバインディングが時々失敗する理由

報告されているng-modelの問題のほとんどは、AngularJSのバグではなく、スコープとプリミティブの動作方法に起因するものです。

典型的なケースは、子スコープを作成するディレクティブ内に配置されたバインディングです。 NGリピート、ng-if または ng-switch。 ng-model="name" 子スコープにシャドウコピーが作成されるため、親スコープでは編集内容が確認できません。代わりにオブジェクトのプロパティにバインドします。 ng-model="user.name" — すべてのスコープが同じ参照を指すようにします。これが、経験豊富な AngularJS 開発者がすべての ng-model 式にドットを入れることを主張する理由です。

残りの大半は、さらに2つの原因によって説明できる。

  • コントローラーまたはモジュールが不足しています。 ng-app または ng-controller のスペルが間違っている場合、バインディングはエラーを発生させるのではなく、何も表示せずに処理を終了します。
  • AngularJS以外で値が変更されました: jQuery ハンドラまたは setTimeout コールバックから設定された値がダイジェスト サイクル外に渡るため、ビューは更新されません。 $scope.$apply() 走る

これら3つの点を確認すれば、動作しないように見えるバインディングの大部分は解決します。

よくあるご質問

ng-bindは一方向です。モデルの値を要素に出力します。ng-modelは双方向で、フォームコントロールでのみ機能するため、ユーザー入力はモデルから出力されるだけでなく、モデルにも反映されます。

例えば、ng-model-options=”{ debounce: 500 }”のようにng-model-optionsを追加します。すると、AngularJSは最後のキー入力から0.5秒後にモデルを更新します。これは、リクエストをトリガーする検索ボックスなどに便利です。

概ねその通りです。AIアシスタントはng-modelを[(ngModel)]に書き換え、FormsModuleのインポートを追加します。リアクティブフォーム、カスタムパーサー、$formattersパイプラインは、Angularがそれらを非常に異なる方法でモデル化するため、手動での確認が必要です。

AIツールは、よくある問題点を迅速にチェックします。例えば、子スコープ内のプリミティブ型バインド、スペルミスのあるコントローラ名、ダイジェストサイクル外で割り当てられた値などです。これらの問題はいずれも、コンソールエラーではなく、サイレントエラーとして処理されます。

入力タイプが「number」の場合のみ、数値として解析されます。タイプが「text」のコントロールは常に文字列を返すため、=== による比較は失敗します。明示的に変換するか、入力タイプを変更してください。