web-dev-qa-db-ja.com

Angular UIモーダルのスコープの問題

angular 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のbody divに追加しようとしましたが、「不明なプロバイダー:$ modalInstanceProvider <-$ modalInstance」というエラーが発生したため、運がありません。

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

80
coblr

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

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

フォーム名、$parentはありません。 AngularUI Bootstrapバージョン0.12.1を使用しています。

this により、この解決策が実現しました。

59
Jason Swett

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

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

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

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

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

より詳細な説明を読む here

66

2014年11月更新

実際、ui-bootstrap 0.12.0にアップグレードすると、コードが機能するはずです。トランスクルードされたスコープはコントローラーのスコープとマージされるため、$parentform.の必要はありません。

.12.0より前

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

<form name="$parent">

または

<form name="$parent.myFormData">

モデルデータはコントローラースコープで使用可能になります。

7
gertas

Scope:$ scopeを追加すると動作します。

1
JBRandri
$scope.open = function () {

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

      };

私の範囲で動作します:$ scopeありがとうu Jason Swett

1
ali Shoaib