Angularjs ng-model non funziona all'interno di ng-if


206

Ecco il violino che mostra il problema. http://jsfiddle.net/Erk4V/1/

Sembra che se ho un ng-model all'interno di un ng-if, il modello non funziona come previsto.

Mi chiedo se si tratti di un bug o se fraintendo l'utilizzo corretto.

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

6
Per una soluzione alternativa puoi usare ng-show = "CONDITION" invece di ng-if. Dovrebbe funzionare.
Hari Das,

Presumo che questo non sia più un problema ora che si può usare controllerAs?
Jamiebarrow,

Ho avuto lo stesso problema quando ho usato una direttiva implicita scope:falsee ho aggiunto ng-ifelementi attorno alla direttiva: gli ambiti erano inizialmente associati, ma si sono separati dopo che un watcher ha aggiornato uno dei valori dell'ambito ...
Aprillion

Risposte:


223

Il ng-if direttiva, come altre direttive, crea un ambito figlio. Vedi lo script qui sotto (o questo 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>

Pertanto, la casella di controllo modifica l' testbambito figlio secondario, ma non l'ambito padre esterno.

Nota che se vuoi modificare i dati nell'ambito genitore, dovrai modificare le proprietà interne di un oggetto come nell'ultima div che ho aggiunto.


1
Come potrei accedere all'ambito di ng-if dalla funzione dei controller principali? Un po 'frustrante. Qual è la ragione di questo?
Justin Carlson,

Non importa, @sza ha appena risposto a questa ^ domanda. Contrassegnerò questa risposta come corretta, dal momento che spiega il motivo esatto che avevo problemi.
Justin Carlson,

21
Questo è uno dei motivi per cui è abbastanza comune usare un oggetto contenitore sul proprio ambito, piuttosto che modificare direttamente le proprietà dell'ambito, come sottolineato nell'esempio: $scope.obj = {...}e ng-model="obj.someProperty"supera questa limitazione.
wulftone,

204

È possibile utilizzare $parentper fare riferimento al modello definito nell'ambito genitore in questo modo

<input type="checkbox" ng-model="$parent.testb" />

16
allora ho ng-model="$parent.$parent.fooperché sono già all'interno di un ambito con un ng-repeat- è davvero il modo migliore?
Chovy

4
questo è davvero confuso. perché? e perché ng-hide ha il suo scopo?
Dominik Goltermann,

5
Re @Gaul: presumibilmente perché ng-hide / ng-show opera sul DOM attuale e aggiunge / rimuove semplicemente una classe CSS, mentre ng-if / ng-switch / ng-ripete tutto il muck con il DOM e tiene traccia dello stato extra . Sembra ragionevole.
trisweb,

4
Sensibile non è la parola che uso.
Jonathan Dumaine,

3
Aggiungi un oggetto all'ambito originale e modifica le proprietà di tale oggetto. ad es. ng-model = "myObject.property". Questo eviterà tutto l'ambito / $ inanità dei genitori. Google "regola del punto angolare" per maggiori informazioni.
Asmor,

50

Puoi usare la direttiva ngHide (o ngShow) . Non crea l'ambito figlio come fa ngIf.

<div ng-hide="testa">

3
Perché ngIfquindi creare un ambito figlio? Mi sembra molto strano.
Freeall

5
Presta attenzione ai commenti della risposta zsong. ng-hidenon cambia la struttura html. Cambia semplicemente gli stili CSS. ng-ifè più complesso: rimuove e inserisce parti html a seconda delle condizioni. Crea un ambito figlio per memorizzare lo stato (almeno dovrebbe memorizzare una parte html nascosta).
Vasiliy Kevroletin,

Sì, lavora per me
Basit

7

Abbiamo avuto questo in molti altri casi, quello che abbiamo deciso internamente è di avere sempre un wrapper per il controller / direttiva in modo da non doverci pensare. Ecco il tuo esempio con il nostro 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>

Spero che questo aiuti, Yishay


3

Sì, la direttiva ng-hide (o ng-show) non creerà un ambito figlio.

Ecco la mia pratica:

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


0

Puoi farlo in questo modo e la tua funzione mod funzionerà perfettamente fammi sapere se vuoi una penna di codice

  <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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.