Angularjs ng-модель не працює всередині ng-if


206

Ось загадка, що показує проблему. http://jsfiddle.net/Erk4V/1/

Це з'являється, якщо у мене є ng-модель всередині ng, якщо модель не працює, як очікувалося.

Мені цікаво, це помилка чи я неправильно розумію правильне використання.

<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елемент навколо директиви - сфери застосування були спочатку зв'язані, але вони відокремилися після того, як спостерігач оновив одне із значень області ...
Апрйон,

Відповіді:


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внутрішню область дочірньої області, але не зовнішню батьківську область.

Зауважте, що якщо ви хочете змінити дані в батьківській області, вам потрібно буде змінити внутрішні властивості об'єкта, як в останньому ділі, який я додав.


1
Як я можу отримати доступ до області ng-if з основної функції контролерів? Трохи засмучує. У чому причина цього?
Джастін Карлсон

Ніколи не пам'ятаю, @sza просто відповів на це ^ питання. Я збираюся відзначити цю відповідь правильною, оскільки це пояснює точну причину виникнення у мене проблем.
Джастін Карлсон

21
Це одна з причин, що досить часто використовувати об'єкт, що містить у своєму масштабі, а не змінювати властивості області безпосередньо, як зазначено в прикладі: $scope.obj = {...}і ng-model="obj.someProperty"долає це обмеження.
wulftone

204

Ви можете використовувати $parentдля позначення моделі, визначеної в батьківській області, як ця

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

16
то я маю, ng-model="$parent.$parent.fooтому що я вже всередині сфери з ng-repeat- це справді найкращий спосіб?
chovy

4
це насправді заплутано. чому так? і чому ng-hid не має власної сфери застосування?
Домінік Голтерманн

5
Re @Gaul: імовірно, тому, що ng-hid / ng-show працює на теперішньому DOM та просто додає / видаляє клас CSS, тоді як ng-if / ng-switch / ng-повторить всі відключення з DOM і слідкує за додатковим станом . Здається розумним.
trisweb

4
Чуттєве - це не слово, яке я вживаю.
Джонатан Дюман

3
Додайте об'єкт до початкової області та змініть його властивості. наприклад, ng-model = "myObject.property". Це дозволить уникнути усієї області / $ батьківської негідності. "Правило кутових точок" від 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-hid (або 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/


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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.