Angularjs нг-модель не работает внутри нг-если

206

Вот скрипка, показывающая проблему. http://jsfiddle.net/Erk4V/1/

Появляется, если у меня есть ng-модель внутри ng-if, модель не работает должным образом.

Мне интересно, если это ошибка или я неправильно понимаю правильное использование.

<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
Для обходного пути вы можете использовать ng-show = "CONDITION" вместо ng-if. Он должен работать.
Хари Дас
Я полагаю, это больше не проблема, которую можно использовать controllerAs?
jamiebarrow
У меня была та же проблема при использовании директивы с неявным, scope:falseи я добавил ng-ifэлемент вокруг директивы - области видимости были связаны изначально, но они стали разделенными после того, как наблюдатель обновил одно из значений области действия ...
Aprillion

Ответы:

223

ng-ifДиректива, как и другие директивы создает дочернюю сферу. Смотрите скрипт ниже (или этот 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>

Таким образом, ваш флажок изменяет testbвнутреннюю часть дочерней области, но не внешнюю родительскую область.

Обратите внимание, что если вы хотите изменить данные в родительской области, вам нужно изменить внутренние свойства объекта, как в последнем добавленном мной div.

Jon7
источник
1
Как мне получить доступ к области действия ng-if из функции основных контроллеров? Немного расстраивает. В чем причина этого?
Джастин Карлсон
Неважно, @sza только что ответил на этот вопрос. Я собираюсь отметить этот ответ как правильный, поскольку он объясняет точную причину, по которой у меня возникли проблемы.
Джастин Карлсон
21
Это одна из причин, по которой довольно часто используется содержащий объект в вашей области вместо непосредственного изменения свойств области, как указано в примере: $scope.obj = {...}и ng-model="obj.someProperty"преодолевает это ограничение.
wulftone
204

Вы можете использовать $parentдля ссылки на модель, определенную в родительской области, как это

<input type="checkbox" ng-model="$parent.testb" />
zs2020
источник
16
тогда у меня есть, ng-model="$parent.$parent.fooпотому что я уже в области с ng-repeat- это действительно лучший способ?
Чови
4
это действительно сбивает с толку. это почему? и почему ng-hide не имеет своей области видимости?
Доминик Гольтерманн
5
Re @Gaul: предположительно, потому что ng-hide / ng-show работает с существующим DOM и просто добавляет / удаляет класс CSS, в то время как ng-if / ng-switch / ng-повторяет всю грязь с DOM и отслеживает дополнительное состояние , Кажется разумным.
trisweb
4
Разумно не то слово, которое я использую.
Джонатан Думайн
3
Добавьте объект в исходную область и измените свойства этого объекта. например, ng-model = "myObject.property". Это позволит обойти всю сферу охвата / $ parent. Google "правило угловых точек" для получения дополнительной информации.
Асмор
50

Вы можете использовать директиву ngHide (или ngShow) . Он не создает дочернюю область, как это делает ngIf.

<div ng-hide="testa">
Василий Кевролетин
источник
3
Почему ngIfтогда создается дочерняя область? Кажется очень странным для меня
Freeall
5
Обратите внимание на комментарии ответа Zsong. ng-hideне меняет структуру HTML. Это просто меняет стили CSS. ng-ifболее сложный: он удаляет и вставляет части HTML в зависимости от состояния. Он создает дочернюю область для сохранения состояния (по крайней мере, он должен хранить скрытую часть HTML).
Василий Кевролетин
Да, работа для меня
Басит
7

У нас это было во многих других случаях, и мы решили, что внутри всегда должна быть оболочка для контроллера / директивы, чтобы нам не приходилось об этом думать. Вот вам пример с нашей оберткой.

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

Надеется, что это помогает, Ишай

Ишай Хаспель
источник
3

Да, директива ng-hide (или ng-show) не создает дочернюю область.

Вот моя практика:

<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
источник
0

Вы можете сделать это так, и ваша мод-функция будет работать идеально, дайте мне знать, если вы хотите кодовое перо

  <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
источник