Angularjs ng-Modell funktioniert nicht in ng-if

206

Hier ist die Geige, die das Problem zeigt. http://jsfiddle.net/Erk4V/1/

Wenn ich ein ng-Modell in einem ng-if habe, funktioniert das Modell nicht wie erwartet.

Ich frage mich, ob dies ein Fehler ist oder ob ich die richtige Verwendung falsch verstehe.

<div ng-app >
    <div ng-controller="main">

        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />

        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="testb" />
        </div>
        <div ng-if="!someothervar">
            testc (with ng-if): <input type="checkbox" ng-model="testc" />
        </div>

    </div>
</div>
Justin Carlson
quelle
6
Für eine Problemumgehung können Sie ng-show = "CONDITION" anstelle von ng-if verwenden. Es sollte funktionieren.
Hari Das
Ich nehme an, dass dies jetzt kein Problem mehr ist, das man verwenden kann controllerAs.
Jamie Barrow
Ich hatte das gleiche Problem bei der Verwendung einer impliziten Direktive scope:falseund fügte ein ng-ifElement um die Direktive hinzu - die Bereiche wurden ursprünglich gebunden, aber sie wurden getrennt, nachdem ein Beobachter einen der Bereichswerte aktualisiert hatte ...
April

Antworten:

223

Die ng-ifDirektive schafft wie andere Direktiven einen untergeordneten Bereich. Siehe das Skript unten (oder diese jsfiddle )

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.obj = {test: false};
    }
</script>

<div ng-app >
    <div ng-controller="main">
        
        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        {{obj.test}}
        
        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="testb" /> {{testb}}
        </div>
        <div ng-if="!someothervar">
            testc (with ng-if): <input type="checkbox" ng-model="testc" />
        </div>
        <div ng-if="!someothervar">
            object (with ng-if): <input type="checkbox" ng-model="obj.test" />
        </div>
        
    </div>
</div>

Ihr Kontrollkästchen ändert also das testbInnere des untergeordneten Bereichs, nicht jedoch den äußeren übergeordneten Bereich.

Beachten Sie, dass Sie, wenn Sie die Daten im übergeordneten Bereich ändern möchten, die internen Eigenschaften eines Objekts wie im letzten von mir hinzugefügten Div ändern müssen.

Jon7
quelle
1
Wie würde ich über die Hauptsteuerungsfunktion auf den Bereich des ng-if zugreifen? Ein bisschen frustrierend. Was ist der Grund dafür?
Justin Carlson
Vergiss nicht, @sza hat gerade diese Frage beantwortet. Ich werde diese Antwort jedoch als richtig markieren, da sie den genauen Grund für meine Probleme erklärt.
Justin Carlson
21
Dies ist ein Grund, warum es ziemlich häufig ist, ein enthaltenes Objekt in Ihrem Bereich zu verwenden, anstatt die Bereichseigenschaften direkt zu ändern, wie im Beispiel gezeigt: $scope.obj = {...}und ng-model="obj.someProperty"diese Einschränkung zu überwinden.
Wulftone
204

Sie können verwenden $parent, um auf das im übergeordneten Bereich definierte Modell wie folgt zu verweisen

<input type="checkbox" ng-model="$parent.testb" />
zs2020
quelle
16
dann habe ich, ng-model="$parent.$parent.fooweil ich schon in einem Bereich mit einem bin ng-repeat- ist das wirklich der beste Weg?
Chovy
4
das ist wirklich verwirrend. warum ist das so? und warum hat ng-hide keinen eigenen bereich?
Dominik Goltermann
5
Zu @Gaul: Vermutlich, weil ng-hide / ng-show auf dem aktuellen DOM ausgeführt wird und nur eine CSS-Klasse hinzugefügt / entfernt wird, während ng-if / ng-switch / ng-alles den ganzen Dreck mit dem DOM wiederholen und den zusätzlichen Status verfolgen . Scheint vernünftig.
Trisweb
4
Sinnvoll ist nicht das Wort, das ich benutze.
Jonathan Dumaine
3
Fügen Sie dem ursprünglichen Bereich ein Objekt hinzu und ändern Sie die Eigenschaften dieses Objekts. zB ng-model = "myObject.property". Dadurch wird der gesamte Umfang / $ Eltern-Irrtum umgangen. Google "Winkelpunktregel" für weitere Informationen.
Asmor
50

Sie können die Anweisung ngHide (oder ngShow) verwenden . Es wird kein untergeordneter Bereich wie ngIf erstellt.

<div ng-hide="testa">
Vasiliy Kevroletin
quelle
3
Warum wird ngIfdann ein untergeordneter Bereich erstellt? Scheint mir sehr seltsam.
freeall
5
Achten Sie auf Kommentare von zsong Antwort. ng-hideändert die HTML-Struktur nicht. Es ändert einfach die CSS-Stile. ng-ifist komplexer: Es entfernt und fügt HTML-Teile je nach Zustand ein. Es wird ein untergeordneter Bereich zum Speichern des Status erstellt (zumindest sollte ein versteckter HTML-Teil gespeichert werden).
Vasiliy Kevroletin
Ja, arbeite für mich
Basit
7

Wir hatten dies in vielen anderen Fällen. Wir haben uns intern entschieden, immer einen Wrapper für den Controller / die Direktive zu haben, damit wir nicht darüber nachdenken müssen. Hier ist Ihr Beispiel mit unserem Wrapper.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
        $scope.thisScope = $scope;
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.testd = false;
    }
</script>

<div ng-app >
    <div ng-controller="main">

        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        Test D: {{testd}}<br />

        <div>
            testa (without ng-if): <input type="checkbox" ng-model="thisScope.testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="thisScope.testb" />
        </div>
        <div ng-show="!testa">
            testc (with ng-show): <input type="checkbox" ng-model="thisScope.testc" />
        </div>
        <div ng-hide="testa">
            testd (with ng-hide): <input type="checkbox" ng-model="thisScope.testd" />
        </div>

    </div>
</div>

Hoffe das hilft, Yishay

Yishay Haspel
quelle
3

Ja, die Anweisung ng-hide (oder ng-show) erstellt keinen untergeordneten Bereich.

Hier ist meine Praxis:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0rc1/angular.min.js"></script>

<script>
    function main($scope) {
        $scope.testa = false;
        $scope.testb = false;
        $scope.testc = false;
        $scope.testd = false;
    }
</script>

<div ng-app >
    <div ng-controller="main">

        Test A: {{testa}}<br />
        Test B: {{testb}}<br />
        Test C: {{testc}}<br />
        Test D: {{testd}}<br />

        <div>
            testa (without ng-if): <input type="checkbox" ng-model="testa" />
        </div>
        <div ng-if="!testa">
            testb (with ng-if): <input type="checkbox" ng-model="$parent.testb" />
        </div>
        <div ng-show="!testa">
            testc (with ng-show): <input type="checkbox" ng-model="testc" />
        </div>
        <div ng-hide="testa">
            testd (with ng-hide): <input type="checkbox" ng-model="testd" />
        </div>

    </div>
</div>

http://jsfiddle.net/bn64Lrzu/

Xiayan Y.
quelle
0

Sie können es so machen und Ihre Mod-Funktion wird perfekt funktionieren. Lassen Sie mich wissen, wenn Sie einen Codestift wollen

  <div ng-repeat="icon in icons">                   
                <div class="row" ng-if="$index % 3 == 0 ">
                    <i class="col col-33 {{icons[$index + n].icon}} custom-icon"></i>
                    <i class="col col-33 {{icons[$index + n + 1].icon}} custom-icon"></i>
                    <i class="col col-33 {{icons[$index + n + 2].icon}} custom-icon"></i>
                </div>
         </div>
Xvegas
quelle