Model Angularjs ng nie działa wewnątrz ng-if

206

Oto skrzypce pokazujące problem. http://jsfiddle.net/Erk4V/1/

Wygląda na to, że jeśli mam model ng wewnątrz ng-if, model nie działa zgodnie z oczekiwaniami.

Zastanawiam się, czy to błąd, czy też nie rozumiem właściwego użycia.

<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
źródło
6
Aby obejść ten problem, możesz użyć ng-show = "CONDITION" zamiast ng-if. To powinno działać.
Hari Das,
Zakładam, że nie jest to już problem, którego można teraz użyć controllerAs?
jamiebarrow
Miałem ten sam problem, gdy korzystałem z dyrektywy niejawnej scope:falsei dodałem ng-ifelement wokół dyrektywy - zakresy były początkowo związane, ale zostały one rozdzielone po tym, jak obserwator zaktualizował jedną z wartości zakresu ...
Aprillion

Odpowiedzi:

223

ng-ifDyrektywa, podobnie jak inne dyrektywy tworzy zakres dzieci. Zobacz poniższy skrypt (lub ten 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>

Zatem pole wyboru zmienia testbwnętrze zakresu potomnego, ale nie zewnętrzny zakres macierzysty.

Zauważ, że jeśli chcesz zmodyfikować dane w zakresie nadrzędnym, musisz zmodyfikować wewnętrzne właściwości obiektu, tak jak w ostatnim div, który dodałem.

Jon7
źródło
1
Jak miałbym uzyskać dostęp do zakresu ng-if z poziomu funkcji głównych kontrolerów? Trochę frustrujące. Jaki jest tego powód?
Justin Carlson,
Nieważne, @sza właśnie odpowiedziała na to ^ pytanie. Zaznaczę tę odpowiedź jako poprawną, ponieważ wyjaśnia ona dokładny powód moich problemów.
Justin Carlson,
21
Jest to jeden z powodów, dla których dość często używa się w swoim zasięgu obiektu zawierającego, zamiast bezpośrednio modyfikować właściwości zakresu, jak wskazano w przykładzie: $scope.obj = {...}i ng-model="obj.someProperty"pokonuje to ograniczenie.
wulftone
204

Możesz użyć, $parentaby odwołać się do modelu zdefiniowanego w zakresie nadrzędnym w ten sposób

<input type="checkbox" ng-model="$parent.testb" />
zs2020
źródło
16
to mam, ng-model="$parent.$parent.fooponieważ już jestem w zasięgu z ng-repeat- czy to naprawdę najlepszy sposób?
chovy
4
to jest naprawdę mylące. dlaczego? i dlaczego ng-hide nie ma własnego zakresu?
Dominik Goltermann
5
Re @Gaul: przypuszczalnie dlatego, że ng-hide / ng-show działa na bieżącym DOM i po prostu dodaje / usuwa klasę CSS, podczas gdy ng-if / ng-switch / ng-repeat cały brud z DOM i śledzi dodatkowy stan . Wydaje się rozsądne.
trisweb,
4
Rozsądne nie jest słowo, którego używam.
Jonathan Dumaine
3
Dodaj obiekt do oryginalnego zakresu i zmień właściwości tego obiektu. np. ng-model = "myObject.property". Spowoduje to ominięcie wszystkich zakresów / $ rodzicielskich inanity. Google „reguła kątowa kropka”, aby uzyskać więcej informacji.
Asmor
50

Możesz użyć dyrektywy ngHide (lub ngShow) . Nie tworzy zasięgu potomnego tak jak ngIf.

<div ng-hide="testa">
Wasilij Kewroletyna
źródło
3
Dlaczego ngIfzatem tworzy zakres potomny? Wydaje mi się to bardzo dziwne.
freeall
5
Zwróć uwagę na komentarze odpowiedzi zsong. ng-hidenie zmienia struktury HTML. Po prostu zmienia style css. ng-ifjest bardziej złożony: usuwa i wstawia części HTML w zależności od stanu. Tworzy zakres potomny do przechowywania stanu (przynajmniej powinien przechowywać ukrytą część HTML).
Vasiliy Kevroletin
Tak, pracuj dla mnie
Basit
7

Mieliśmy to w wielu innych przypadkach, dlatego zdecydowaliśmy wewnętrznie, aby zawsze mieć opakowanie na kontroler / dyrektywę, abyśmy nie musieli o tym myśleć. Oto twój przykład z naszą owijarką.

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

Mam nadzieję, że to pomoże, Yishay

Yishay Haspel
źródło
3

Tak, dyrektywa ng-hide (lub ng-show) nie utworzy zasięgu potomnego.

Oto moja praktyka:

<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
źródło
0

Możesz to zrobić w ten sposób, a funkcja mod będzie działać idealnie, daj mi znać, jeśli chcesz pióro kodowe

  <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
źródło