Umfangsprobleme mit Angular UI modal

80

Ich habe Probleme, die Bereiche für ein eckiges UI-Modal zu verstehen / zu verwenden.

Obwohl dies hier nicht sofort ersichtlich ist, habe ich die Module und alles richtig eingerichtet (soweit ich das beurteilen kann), aber gerade in diesen Codebeispielen finde ich den Fehler.

index.html (der wichtige Teil davon)

<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 (wieder der wichtige Teil)

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 (in seiner Gesamtheit)

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

Meine Frage lautet also: Warum ist der Bereich nicht doppelt an die Benutzeroberfläche gebunden? und warum hat thisdie angepassten Werte, aber $scopenicht?

Ich habe versucht, ng-controller="AppCreateCtrl"das Body-Div in create.html hinzuzufügen, aber das hat einen Fehler ausgelöst: "Unbekannter Anbieter: $ modalInstanceProvider <- $ modalInstance", also kein Glück.

An diesem Punkt besteht meine einzige Möglichkeit darin, ein Objekt mit this.nameund this.groupTypeanstatt zu verwenden $scope, aber das fühlt sich falsch an.

coblr
quelle
Gute Modal Scope Diskussion hier: github.com/mgcrea/angular-strap/issues/14
Steampowered

Antworten:

60

Ich habe meine dazu gebracht, so zu arbeiten:

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

Kein Formularname, nein $parent. Ich verwende AngularUI Bootstrap Version 0.12.1.

Dadurch wurde ich auf diese Lösung hingewiesen .

Jason Swett
quelle
Dies ist eine viel bessere Lösung. Viel sauberer. Wir haben erst kürzlich ein Upgrade auf 0.12.1 durchgeführt und korrigieren derzeit die eingeführten Änderungen. Ich kann dies zur Liste hinzufügen. Vielen Dank!!
Coblr
Ich akzeptiere diese Antwort, weil es sich um die aktuelle Implementierung handelt und für diejenigen, die hier landen und versuchen, die Dinge zum Laufen zu bringen, nützlicher ist. Bitte lesen Sie den vollständigen Thread, es sei denn, Sie verwenden die neueste (~ 0.12) Version von Angular UI.
Coblr
Das Modal scheint nicht mit $ modalStack verschließbar zu sein, wenn sich der Status geändert hat, wenn der Bereich festgelegt ist
Phazei
Hallo, dies hat mein Problem für eine Weile gelöst, aber beim Schließen des Modals / Dialogs ist etwas Seltsames aufgefallen. Der Inhalt hat sich geändert und es schien etwas mit einem Scope-Objekt zu tun zu haben. Hinzufügen von scope: $ scope ,erveScope: true // <- wichtig hat irgendwie geholfen! Ich weiß nicht genau warum, aber ich habe es auf material.angularjs.org/latest/api/service/ gefunden. Bearbeiten: Ich habe herausgefunden warum. Wenn Sie den Bereich festlegen: für das Dialogfeld, und schließen Sie dann den Dialog "Dieser Bereich wird zerstört, wenn das untere Blatt entfernt wird, es sei denn ,erveScope ist auf true festgelegt."
Max
In meinem Controller verwende ich vm = this. Ich verwende $ scope nicht. Was soll ich dann dem Geltungsbereich zuweisen?
Ankit Prajapati
66

Wenn verschachtelte Bereiche betroffen sind, binden Sie <input>s nicht direkt an Mitglieder des Bereichs:

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

Binden Sie sie mindestens eine Ebene tiefer:

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

Der Grund dafür ist, dass Bereiche prototypisch ihren übergeordneten Bereich erben. Wenn Sie also Mitglieder der ersten Ebene festlegen, werden diese direkt im untergeordneten Bereich festgelegt, ohne dass dies Auswirkungen auf die übergeordneten Elemente hat. Im Gegensatz dazu wird form.namedas Mitglied beim Binden an verschachtelte Felder ( ) formaus dem übergeordneten Bereich gelesen, sodass beim Zugriff auf die nameEigenschaft auf das richtige Ziel zugegriffen wird.

Lesen Sie eine ausführliche Beschreibung hier .

Nikos Paraskevopoulos
quelle
14
Während das Ändern in 'form.name' nichts bewirkt hat, wurde das Problem durch Ändern in ng-model = "$ parent.name" behoben. Vielen Dank! (und danke auch für das Lesematerial. Habe dieses noch nicht gesehen.)
Coblr
1
Wenn Sie die controller asSyntax verwenden, werden Sie nicht auf solche Probleme mit verschachtelten Bereichen stoßen
rauben Sie den
Wie ist die controller as Syntax?
Adrianboimvaser
1
Siehe docs.angularjs.org/api/ng.directive:ngController . Grundsätzlich mache ich ng-controller = "MyCtrl as my" und verweise dann auf ein ng-Modell wie my.someVar
Ryan Q
2
@Nikos Paraskevopoulos, Was bedeutet "form.name"? Es wird im bereitgestellten Code überhaupt nicht erwähnt!
ŁukaszBachman
7

Update November 2014 :

Eigentlich sollte Ihr Code nach dem Upgrade auf ui-bootstrap 0.12.0 funktionieren. Der transkludierte Bereich wird mit dem Bereich des Controllers zusammengeführt, sodass kein Bedarf $parentoder form.ähnliches mehr besteht.

Vor 0.12.0 :

Das Modal verwendet die Transklusion, um seinen Inhalt einzufügen. Dank ngFormkönnen Sie den Bereich nach nameAttributen steuern . Um dem ausgeschlossenen Bereich zu entkommen, ändern Sie das Formular einfach folgendermaßen:

<form name="$parent">

oder

<form name="$parent.myFormData">

Die Modelldaten werden im Controller-Bereich verfügbar sein.

gertas
quelle
Wollen Sie klar sagen, dass der Bereich des Controllers, in dem Sie anrufen $modal, für den Controller verfügbar sein sollte, der dem Modal zugewiesen ist?
Jason Swett
Nein, das Problem war, dass selbst der modale Instanz-Controller für Formulare nicht leicht zugänglich war. Um auf den Controller zuzugreifen, der das Modal öffnet, geben Sie einfach scope:$scope$ modal.open params map ein.
Gertas
Meinen Sie Angular UI? Unterscheidet sich das von UI Bootstrap?
Noah
1
$scope.open = function () {

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

      };

es funktioniert für mich scope: $ scope danke u Jason Swett

ali Shoaib
quelle
1

Ich füge scope hinzu: $ scope dann funktioniert es .Cool

JBRandri
quelle