AngularUIモーダルのスコープの問題


80

角度のあるUIモーダルのスコープを理解/使用するのに問題があります。

ここではすぐにはわかりませんが、モジュールとすべてが正しくセットアップされています(私が知る限り)が、特にこれらのコードサンプルはバグを見つけた場所です。

index.html(その重要な部分)

<div class="btn-group">
    <button class="btn dropdown-toggle btn-mini" data-toggle="dropdown">
        Actions
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu pull-right text-left">
        <li><a ng-click="addSimpleGroup()">Add Simple</a></li>
        <li><a ng-click="open()">Add Custom</a></li>
        <li class="divider"></li>
        <li><a ng-click="doBulkDelete()">Remove Selected</a></li>
    </ul>
</div>

Controller.js(ここでも重要な部分)

MyApp.controller('AppListCtrl', function($scope, $modal){
    $scope.name = 'New Name';
    $scope.groupType = 'New Type';

    $scope.open = function(){
        var modalInstance = $modal.open({
            templateUrl: 'partials/create.html',
            controller: 'AppCreateCtrl'
        });
        modalInstance.result.then(function(response){

            // outputs an object {name: 'Custom Name', groupType: 'Custom Type'}
            // despite the user entering customized values
            console.log('response', response);

            // outputs "New Name", which is fine, makes sense to me.                
            console.log('name', $scope.name);

        });
    };
});

MyApp.controller('AppCreateCtrl', function($scope, $modalInstance){
    $scope.name = 'Custom Name';
    $scope.groupType = 'Custom Type';

    $scope.ok = function(){

        // outputs 'Custom Name' despite user entering "TEST 1"
        console.log('create name', $scope.name);

        // outputs 'Custom Type' despite user entering "TEST 2"
        console.log('create type', $scope.groupType);

        // outputs the $scope for AppCreateCtrl but name and groupType
        // still show as "Custom Name" and "Custom Type"
        // $scope.$id is "007"
        console.log('scope', $scope);

        // outputs what looks like the scope, but in this object the
        // values for name and groupType are "TEST 1" and "TEST 2" as expected.
        // this.$id is set to "009" so this != $scope
        console.log('this', this);

        // based on what modalInstance.result.then() is saying,
        // the values that are in this object are the original $scope ones
        // not the ones the user has just entered in the UI. no data binding?
        $modalInstance.close({
            name: $scope.name,
            groupType: $scope.groupType
        });
    };
});

create.html(全体)

<div class="modal-header">
    <button type="button" class="close" ng-click="cancel()">x</button>
    <h3 id="myModalLabel">Add Template Group</h3>
</div>
<div class="modal-body">
    <form>
        <fieldset>
            <label for="name">Group Name:</label>
            <input type="text" name="name" ng-model="name" />           
            <label for="groupType">Group Type:</label>
            <input type="text" name="groupType" ng-model="groupType" />
        </fieldset>
    </form>
</div>
<div class="modal-footer">
    <button class="btn" ng-click="cancel()">Cancel</button>
    <button class="btn btn-primary" ng-click="ok()">Add</button>
</div>

だから、私の質問は立っています:なぜスコープがUIに二重にバインドされていないのですか?なぜthisカスタマイズされた値があるのに、$scopeないのですか?

ng-controller="AppCreateCtrl"create.htmlのbodydivに追加しようとしましたが、「不明なプロバイダー:$ modalInstanceProvider <-$ modalInstance」というエラーが発生したため、運がありません。

この時点で、私の唯一のオプションはでオブジェクトを返すためであるthis.namethis.groupType代わりに使用するのでは$scope、それは間違って感じています。


ここでの優れたモーダルスコープの議論:github.com/mgcrea/angular-strap/issues/14
Steampowered

回答:


60

私は私のように働くようになりました:

var modalInstance = $modal.open({
  templateUrl: 'partials/create.html',
  controller: 'AppCreateCtrl',
  scope: $scope // <-- I added this
});

フォーム名なし、いいえ$parent。AngularUIBootstrapバージョン0.12.1を使用しています。

私はこれによってこの解決策にひっくり返されました


これははるかに優れたソリューションです。はるかにきれい。最近0.12.1にアップグレードし、現在、導入された重大な変更を修正しています。これをリストに追加できます。ありがとう!
coblr 2015年

これは現在の実装であり、物事を機能させようとしてここにたどり着く人にとってより役立つため、私はこの回答を受け入れています。最新(〜0.12)バージョンのAngular UIを使用していない限り、スレッド全体をお読みください。
coblr 2015年

スコープが設定されている場合に状態が変更された場合、モーダルは$ modalStackで閉じることができないようです
phazei 2015

こんにちは、これはしばらくの間私の問題を解決しましたが、モーダル/ダイアログを閉じるときに奇妙なことに気づきました。コンテンツが変更され、スコープオブジェクト上の何かが混乱しているように見えました。スコープの追加:$ scope、preserveScope:true // <-どういうわけか重要な助けになりました!理由は完全にはわかりませんが、material.angularjs.org / latest / api / service /で見つかりました…編集:理由がわかりました。ダイアログにscope:を設定し、ダイアログを閉じると、「preserveScopeがtrueに設定されていない限り、このスコープは下部のシートが削除されると破棄されます。」
最大

私のコントローラーでは、vm = thisを使用しています。$ scopeを使用していません。次に、スコープに何を割り当てる必要がありますか?
Ankit Prajapati 2018

66

ネストされたスコープが含まれる場合<input>は、スコープのメンバーに直接バインドしないでください。

<input ng-model="name" /> <!-- NO -->

それらを少なくともより深いレベルにバインドします。

<input ng-model="form.name" /> <!-- YES -->

その理由は、スコープは典型的には親スコープを継承するためです。したがって、第1レベルのメンバーを設定する場合、これらは親に影響を与えることなく、子スコープに直接設定されます。それとは対照的に、ネストされたフィールド(form.name)にバインドすると、メンバーformは親スコープから読み取られるため、nameプロパティにアクセスすると正しいターゲットにアクセスします。

ここでより詳細な説明を読んでください


14
これを「form.name」に変更しても何も起こりませんでしたが、ng-model = "$ parent.name"に変更すると問題が修正されました。ありがとう!(そして、読み物にも感謝します。これはまだ見ていません。)
coblr 2013

1
controller as構文を使用する場合、このようなネストされたスコープの問題に遭遇することはありません
rob

controller as 構文は?
adrianboimvaser 2014年

1
docs.angularjs.org/api/ng.directive:ngControllerを参照してください。基本的にng-controller = "MyCtrl as my"を実行してから、my.someVarのようなng-modelを参照します
Ryan Q

2
@Nikos Paraskevopoulos、「form.name」は何を表していますか?提供されているコードにはまったく記載されていません。
ŁukaszBachman

7

2014年11月の更新

実際、コードはui-bootstrap0.12.0にアップグレードした後に機能するはずです。トランスクルード範囲はこれ以上の必要ので、コントローラのスコープにマージされる$parentform.のもの。

0.12.0より前

モーダルは、トランスクルージョンを使用してその内容を挿入します。おかげでngFormname属性によってスコープを制御できます。したがって、トランスクルージョンされたスコープをエスケープするには、次のようにフォームを変更するだけです。

<form name="$parent">

または

<form name="$parent.myFormData">

モデルデータはコントローラースコープで利用できます。


明確にするために、あなたが呼び出しているコントローラーのスコープは$modal、モーダルに割り当てられたコントローラーが利用できるべきだと言っていますか?
Jason Swett 2015年

いいえ、問題は、モーダルインスタンスコントローラーでさえフォームから簡単にアクセスできないことでした。モーダルを開くコントローラーにアクセスするにはscope:$scope、$ modal.openparamsマップに入力するだけです。
gertas 2015年

Angular UIのことですか?それはUIBootstrapとは異なりますか?
ノア

1
$scope.open = function () {

          var modalInstance = $uibModal.open({
              animation: $scope.animationsEnabled,
              templateUrl: 'myModalContent.html',
              controller: 'salespersonReportController',
              //size: size
              scope: $scope
            });

      };

それは私のために働きますスコープ:$ scopeありがとうuJason Swett


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.