O ng-model do Angularjs não funciona dentro do ng-if


206

Aqui está o violino mostrando o problema. http://jsfiddle.net/Erk4V/1/

Parece que se eu tiver um modelo ng dentro de um ng-if, o modelo não funcionará conforme o esperado.

Gostaria de saber se isso é um bug ou se estou entendendo mal o uso adequado.

<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
Para uma solução alternativa, você pode usar ng-show = "CONDITION" em vez de ng-if. Deveria funcionar.
Hari Das

Presumo que isso não é mais um problema agora que se pode usar controllerAs?
21716 Jamiebarrow

Eu tive o mesmo problema ao usar uma directiva com implícita scope:falsee acrescentei ng-ifelemento em torno da directiva - os âmbitos eram obrigados inicialmente, mas eles se separaram depois de um observador atualizadas um dos valores de escopo ...
Aprillion

Respostas:


223

A ng-ifdiretiva, como outras diretivas, cria um escopo filho. Veja o script abaixo (ou este 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>

Portanto, sua caixa de seleção altera o testbinterior do escopo filho, mas não o escopo pai externo.

Observe que, se você quiser modificar os dados no escopo pai, precisará modificar as propriedades internas de um objeto, como na última div que eu adicionei.


1
Como eu acessaria o escopo do ng-if a partir da função dos controladores principais? Um pouco frustrante. Qual o motivo disso?
23813 Justin Carson

Deixa pra lá, @sza acabou de responder a essa pergunta. Vou marcar esta resposta como correta, pois explica o motivo exato pelo qual eu estava tendo problemas.
Justin Carlson

21
Esse é um dos motivos pelos quais é bastante comum usar um objeto que contenha seu escopo, em vez de modificar diretamente as propriedades do escopo, como apontado no exemplo: $scope.obj = {...}e ng-model="obj.someProperty"supera essa limitação.
Wulftone 22/10

204

Você pode usar $parentpara se referir ao modelo definido no escopo pai como este

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

16
então eu tenho ng-model="$parent.$parent.fooporque eu já estou dentro de um escopo com um ng-repeat- este é realmente o melhor caminho?
Chovy

4
isso é realmente confuso. por que é que? e por que o ng-hide não tem escopo próprio?
Dominik Goltermann 03/03

5
Re @Gaul: presumivelmente porque ng-hide / ng-show opera no DOM atual e apenas adicione / remova uma classe CSS, enquanto ng-if / ng-switch / ng-repeat todo o lixo com o DOM e acompanhe o estado extra . Parece sensato.
trisweb

4
Sensível não é a palavra que eu uso.
Jonathan Dumaine

3
Adicione um objeto ao escopo original e altere as propriedades desse objeto. por exemplo, ng-model = "myObject.property". Isso contornará toda a escopo / $ inanity pai. Google "regra de ponto angular" para mais informações.
Asmor 16/02

50

Você pode usar a diretiva ngHide (ou ngShow) . Não cria escopo filho como ngIf.

<div ng-hide="testa">

3
Por que, ngIfentão, cria um escopo filho? Parece muito estranho para mim.
freeall

5
Preste atenção aos comentários da resposta zsong. ng-hidenão altera a estrutura html. Simplesmente muda os estilos de CSS. ng-ifé mais complexo: remove e insere peças html, dependendo da condição. Ele cria o escopo filho para armazenar o estado (pelo menos deve armazenar parte html oculta).
Vasiliy Kevroletin

Sim, trabalhe para mim
Basit 02/04

7

Tivemos isso em muitos outros casos, o que decidimos internamente é sempre ter um wrapper para a diretiva / controlador, para que não precisemos pensar sobre isso. Aqui está seu exemplo com nosso invólucro.

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

Espera que isso ajude, Yishay


3

Sim, a diretiva ng-hide (ou ng-show) não criará escopo filho.

Aqui está a minha prática:

<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

Você pode fazer assim e sua função mod funcionará perfeitamente, deixe-me saber se você quer uma caneta de código

  <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>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.