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.