16

複数のフォームを含むページがあり、一度に 1 つだけ表示したい。このために、各フォームをセクションに分割し、Bootstrap のアコーディオン プラグインを使用して、一度に 1 つのセクションしか開かないようにしました。

私のマークアップは次のようになります。

<a ng-click="open_section('section1')">Section 1</a>

<div collapse="section1">
  <form name="section1Form">
  </form>
</div>

<a ng-click="open_section('section2')">Section 2</a>

<div collapse="section2">
  <form name="section2Form">
  </form>
</div>

すべてがうまく機能し、フォーム間などを移動できます。

現在編集中のセクションに検証エラーが含まれている場合、ユーザーにセクションを開いてほしくないので、open_section関数に関連付けられているフォームが有効かどうかをチェックインしてみました。

やってみましたが、できませんでした。ページを担当するコントローラー内のフォームに関連付けられた FormController にアクセスできませんでした。何らかの理由で、スコープで公開されていません。

これは私が試したものです:

  • $scope.section1Formundefined

  • で試しましたが$scope.$watch('section1Form, function(){})、まだ未定義です

  • フォームの名前を 2 番目のパラメーターとして追加しようとしましたopen_sectionopen_section('section1', section1Form)、関数では 2 番目の引数はundefined.

タグの間で<form></form>は FormController にアクセスできますが、タグの外ではアクセスできません。イベントは<form>(セクションの終了、開始)の外部から発生しているため、フォームの有効性を確認するために FormController をコントローラーに渡すことができません。

これを回避する方法はありますか、それともページをリファクタリングする必要がありますか?

私はAngular 1.1.5 btwを使用しています。

また、AngularJS Batarang Chrome プラグインで確認すると、フォームが現在のスコープの子スコープとして公開されていることがわかります。

編集:これは、スコープ階層がこのアプリを探す方法です

 - root
 |
 ---current controller\'s scope
 |
 ----scope that contains the forms

これは私が使用しているからですng-includeか?コントローラーでこれらのフォームにアクセスする方法はありませんか?

4

10 に答える 10

16

動的フォームを処理するため、つまり関連する FormController の動的な場所を処理するために、単純なディレクティブを使用して、フォームを含むスコープを見つけやすくしました。

解決:

$emit がフォームに関連付けられたスコープであるディレクティブを作成します。

  module.directive('formLocator', function() {
    return {
      link: function(scope) {
        scope.$emit('formLocator');
      }
    }

マークアップで次のディレクティブを使用します。

<form name="myForm" novalidate form-locator>

コントローラーのディレクティブによってイベント ブロードキャストをリッスンします。

$scope.$on('formLocator', function(event) {
  $scope.myDeeplyNestedForm = event.targetScope.myForm;
});
于 2014-03-18T18:22:26.017 に答える
7

スコープ階層内でオブジェクトを検索するAngularプロセスを使用して、スコープ階層内で通信するはるかに簡単な方法があります。

これにより、ドット表記を使用して、オブジェクトを下位スコープから上位スコープにアタッチできます。

この場合、最上位コントローラに「キャッチャー」の空のオブジェクトを作成する必要があります。このキャッチャー オブジェクトは、下位のスコープからフォーム オブジェクトを割り当てることができます。これがデモ用のプランクです。

http://plnkr.co/edit/xwsu48bjM3LofAoaRDsN?p=preview

これは完全にエレガントではありませんが、この「キャッチャー」オブジェクトをイベント リスナーと考え​​れば、標準的なパターンに従っています。

ネストされたフォームへの参照が必要なコントローラーに空のキャッチャーオブジェクトを作成します

function mainController($scope){
  $scope.catcher = {

  };
 }

次に、ng-form ディレクティブが宣言されるたびにマークアップ自体で、 catcher.formName = formName を次のように設定します。

<ng-form name="alpha">
          <span ng-init="catcher.alpha = alpha"></span>
          <input type="text" required="" ng-model="alphaValue" />
        </ng-form>

"catcher." に割り当てられているため、angular はスコープ階層を上に移動し、その間のコントローラーの数に関係なく、mainController でそれを見つけます (もちろん、キャッチャー オブジェクトもないと仮定します)。

于 2014-06-30T17:32:18.320 に答える
5

フォームで部分ビューを使用していたためng-view、コントローラーの子スコープに登録されていました。プロトタイプの継承により、親スコープから子スコープにアクセスできないようです。

そうは言っても、アコーディオンの開閉を担当する関数を介してフォームコントローラーインスタンスを渡すことで、コントローラーにフォームコントローラーインスタンスを取得することができました。

解決策は次のようなものです。

<a ng-click="open_section('section1', section1Form)">Section 1</a>

<div collapse="section1">
  <form name="section1Form">
  </form>
</div>

<a ng-click="open_section('section2', section2Form)">Section 2</a>

<div collapse="section2">
  <form name="section2Form">
  </form>
</div>
于 2013-10-02T23:07:42.573 に答える
4

angularドキュメントでは、次を読むことができます:

<form
       [name="{string}"]>
</form>

フォームの名前。指定した場合、フォーム コントローラーはこの名前で関連するスコープに公開されます。

ただし、新しいスコープを作成するngIfなどの特定のディレクティブがあります。

要素が ngIf を使用して削除されると、そのスコープは破棄され、要素が復元されると新しいスコープが作成されることに注意してください。

それはあなたの場合ですか?その場合は、フォーム名を「forms.section1Form」などに設定してから、スコープ内でそれに応じてアクセスできます。

于 2013-10-02T15:24:35.363 に答える
4

ディレクティブ、コントローラーなどからフォームにアクセスするには、ng-init を利用できます。

例えば:

  <form name="myForm">
     <div ng-init="myLocalScopeVar=form"></div

    <input name="myField" ....>
  </form>

フォーム データにアクセスしたり、これがディレクティブの場合はバインドされた変数で返すことができます。上記のテンプレートのコントローラーでの例:

     if ($scope.myLocalScopeVar.myField.$valid ) ...

これは、フォームを親 $scope に保存するという点で、 Sinil D の回答の素晴らしい回答に似ていますが、イベントは使用しません。基本的に同じことを行っていますが、オーバーヘッドが少し少なくなっています。

于 2014-04-02T12:19:09.580 に答える
2

フォームのスコープを親スコープに提供する Sunil D. の斬新なソリューション ( https://stackoverflow.com/a/22487840/1518575を参照) に関しては、$ で送信されるイベント オブジェクトからフォームのスコープを実際に取得できます。コールを発します。

少なくとも Angular 1.0.3 以降、イベント オブジェクトには targetScope プロパティがあり、イベントが $emit-ed されたスコープを参照します。(イベント オブジェクトのプロパティの詳細については、 http: //docs.angularjs.org/api/ng/type/$rootScope.Scope#$on を参照してください。)

これを念頭に置いて、Sunil D. のディレクティブ コードを次のように単純化できます。

module.directive('formLocator', function() {
  return {
    link: function(scope) {
      scope.$emit('formLocator');
    }
  };
});

テンプレートはまったく変更されません。

<form name="myForm" novalidate="" form-locator>

その後、イベント処理コードを次のように変更します。

$scope.$on('formLocator', function(event) {
  $scope.myDeeplyNestedForm = event.targetScope.myForm;
});

このディレクティブは、ngForm の場合だけでなく、その先祖の 1 つにスコープを提供する必要があるあらゆるシナリオに関連します。私のコードベースでは、このディレクティブの名前をより一般的な「present」に変更しました。これは、ディレクティブの目的を考える 1 つの方法は、スコープの存在をアナウンスすることだからです。

于 2014-04-17T15:47:41.440 に答える
2

コントローラーがフォームの外側にあるか、フォームがスコープに入力される前にフォームを取得しようとしている可能性があります。

PlunkRを作成しましたが、うまくいきました。

于 2013-10-02T15:59:03.967 に答える
0

Sunil D. ソリューションと同様に、同様のソリューションに出くわしましたが、フォームの名前を 2 回ハードコーディングしたくなかったため、タグが使用された formController であるスコープ変数に暗黙的に設定します。

renderFormModule.directive('formLocator', function() {
    return {
        link: function(scope, element) {
            scope.formAssociated = scope[element[0].name];
        }
    }
});

そして、次のようなビュー:

    <form name="testForm" ng-controller='formController as formCtrl' form-locator novalidate>
于 2016-02-10T12:57:05.923 に答える
0

私はこれが多くの恐怖を引き起こすことを知っています....しかし、私は非常に怠惰で、以下を使用しました(監視として追加され、すべてのダイジェストを実行するため、大きなオーバーヘッドが発生しないと信じたいです):

<form name = "formName" nf-if="someCondition">

{{(controller.referenceToForm==undefined && (controller.referenceToForm=formName) != undefined)?'':''}}

</form>

次にcontroller.referenceToForm、コントローラー内などで使用します。

于 2015-11-06T14:23:53.730 に答える