Проблеми із сферою застосування модального інтерфейсу Angular UI


80

У мене проблеми з розумінням / використанням областей застосування для кутового модального інтерфейсу.

Хоча тут це не видно відразу, у мене є модулі і все налаштовано правильно (наскільки я можу зрозуміти), але саме ці зразки коду я знаходжу тут.

index.html (важлива його частина)

<div class="btn-group">
    <button class="btn dropdown-toggle btn-mini" data-toggle="dropdown">
        Actions
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu pull-right text-left">
        <li><a ng-click="addSimpleGroup()">Add Simple</a></li>
        <li><a ng-click="open()">Add Custom</a></li>
        <li class="divider"></li>
        <li><a ng-click="doBulkDelete()">Remove Selected</a></li>
    </ul>
</div>

Controller.js (знову ж таки важлива частина)

MyApp.controller('AppListCtrl', function($scope, $modal){
    $scope.name = 'New Name';
    $scope.groupType = 'New Type';

    $scope.open = function(){
        var modalInstance = $modal.open({
            templateUrl: 'partials/create.html',
            controller: 'AppCreateCtrl'
        });
        modalInstance.result.then(function(response){

            // outputs an object {name: 'Custom Name', groupType: 'Custom Type'}
            // despite the user entering customized values
            console.log('response', response);

            // outputs "New Name", which is fine, makes sense to me.                
            console.log('name', $scope.name);

        });
    };
});

MyApp.controller('AppCreateCtrl', function($scope, $modalInstance){
    $scope.name = 'Custom Name';
    $scope.groupType = 'Custom Type';

    $scope.ok = function(){

        // outputs 'Custom Name' despite user entering "TEST 1"
        console.log('create name', $scope.name);

        // outputs 'Custom Type' despite user entering "TEST 2"
        console.log('create type', $scope.groupType);

        // outputs the $scope for AppCreateCtrl but name and groupType
        // still show as "Custom Name" and "Custom Type"
        // $scope.$id is "007"
        console.log('scope', $scope);

        // outputs what looks like the scope, but in this object the
        // values for name and groupType are "TEST 1" and "TEST 2" as expected.
        // this.$id is set to "009" so this != $scope
        console.log('this', this);

        // based on what modalInstance.result.then() is saying,
        // the values that are in this object are the original $scope ones
        // not the ones the user has just entered in the UI. no data binding?
        $modalInstance.close({
            name: $scope.name,
            groupType: $scope.groupType
        });
    };
});

create.html (повністю)

<div class="modal-header">
    <button type="button" class="close" ng-click="cancel()">x</button>
    <h3 id="myModalLabel">Add Template Group</h3>
</div>
<div class="modal-body">
    <form>
        <fieldset>
            <label for="name">Group Name:</label>
            <input type="text" name="name" ng-model="name" />           
            <label for="groupType">Group Type:</label>
            <input type="text" name="groupType" ng-model="groupType" />
        </fieldset>
    </form>
</div>
<div class="modal-footer">
    <button class="btn" ng-click="cancel()">Cancel</button>
    <button class="btn btn-primary" ng-click="ok()">Add</button>
</div>

Отже, моє запитання стоїть: чому область дії не подвійно прив’язана до інтерфейсу користувача? а чому thisмає індивідуальні значення, але $scopeні?

Я намагався додати ng-controller="AppCreateCtrl"до тіла div у create.html, але це призвело до помилки: "Невідомий постачальник: $ modalInstanceProvider <- $ modalInstance", тому там не пощастило.

На даний момент, мій єдиний варіант - повернути об’єкт із використанням this.nameта this.groupTypeзамість нього $scope, але це здається неправильним.


Хороша дискусія про модальний обсяг тут: github.com/mgcrea/angular-strap/issues/14
'18

Відповіді:


60

Я змусив свою працювати так:

var modalInstance = $modal.open({
  templateUrl: 'partials/create.html',
  controller: 'AppCreateCtrl',
  scope: $scope // <-- I added this
});

Немає назви форми, немає $parent . Я використовую AngularUI Bootstrap версії 0.12.1.

Я був попереджений до цього рішення по цим .


Це набагато краще рішення. Набагато чистіше. Нещодавно ми оновили версію 0.12.1 і наразі виправляємо внесені зміни. Я можу додати це до списку. Дякую!!
coblr

Я приймаю цю відповідь, оскільки це поточне впровадження і буде кориснішим тим, хто опиняється тут, намагаючись змусити щось працювати. Будь ласка, прочитайте повну тему, якщо ви не використовуєте останню (~ 0,12) версію Angular UI.
coblr

Здається, модаль не можна закрити за допомогою $ modalStack, якщо стан змінився, якщо встановлено область дії
phazei

Привіт, це на деякий час вирішило мою проблему, але під час закриття модального / діалогового вікна помітив дивну річ, зміст змінювався, і здавалося, що він щось із вашим на об’єкті сфери. додавання області: $ scope ,serveScope: true // <- важливо якось допомогло! не повністю впевнений, чому, але знайшов це на material.angularjs.org/latest/api/service/… Редагувати: Я з’ясував, чому. коли ви встановлюєте область: для діалогового вікна, а потім закриваєте діалогове вікно "Ця область буде знищена, коли нижній аркуш буде видалено, якщо для параметра SaveScope не встановлено значення".
Макс.

У своєму контролері я використовую vm = this. Я не використовую $ scope. Тоді що я повинен призначити обсягу?
Ankit Prajapati

66

Коли задіяні вкладені області, не прив'язуйте <input>s безпосередньо до членів області:

<input ng-model="name" /> <!-- NO -->

Прив’яжіть їх як мінімум до рівня глибше:

<input ng-model="form.name" /> <!-- YES -->

Причина полягає в тому, що сфери дії прототипово успадковують батьківський обсяг. Отже, при встановленні учасників 1-го рівня, вони встановлюються безпосередньо в дочірній області, не впливаючи на батьків. На відміну від цього, при прив'язуванні до вкладених полів ( form.name) член formчитається з батьківської області, тому доступ доname властивості отримує доступ до правильної цілі.

Детальніший опис читайте тут .


14
Хоча зміна цього на 'form.name' нічого не зробила, зміна на ng-model = "$ parent.name" вирішила проблему. Дякую! (і подяка також за прочитаний матеріал. Цього ще не бачив.)
coblr

1
Якщо ви використовуєте controller asсинтаксис, тоді ви не зіткнетеся з такими проблемами вкладеного обсягу
пограбуйте

Який controller as синтаксис?
adrianboimvaser

1
Див. Docs.angularjs.org/api/ng.directive:ngController . В основному роблячи ng-controller = "MyCtrl як мій", потім посилаючись на ng-модель, подібну до my.someVar
Райан Q

2
@Nikos Paraskevopoulos, Що означає "form.name"? Це взагалі не згадується у наданому коді!
kasukaszBachman

7

Оновлення в листопаді 2014 року :

Насправді ваш код повинен працювати після оновлення до ui-bootstrap 0.12.0. Приціл включений через злитий з розмахом контролера так більше не потрібно для $parentабо form.речей.

До 0.12.0 :

Модаль використовує переключення, щоб вставити його вміст. Завдяки ngFormвам ви можете контролювати область дії за nameатрибутом. Отже, щоб уникнути включеної області просто модифікуйте форму таким чином:

<form name="$parent">

або

<form name="$parent.myFormData">

Дані моделі будуть доступні в межах контролера.


Щоб бути зрозумілим, ви хочете сказати, що область дії контролера, всередині якого ви телефонуєте, $modalповинна бути доступна контролеру, призначеному модальному?
Джейсон Світт,

Ні, проблема полягала в тому, що навіть модальний контролер екземпляра не був легко доступним для форм. Щоб отримати доступ до контролера, який відкриває модаль, просто scope:$scopeвведіть $ modal.open map params.
gertas

Ви маєте на увазі кутовий інтерфейс? Чим це відрізняється від інтерфейсу Bootstrap?
Ной

1
$scope.open = function () {

          var modalInstance = $uibModal.open({
              animation: $scope.animationsEnabled,
              templateUrl: 'myModalContent.html',
              controller: 'salespersonReportController',
              //size: size
              scope: $scope
            });

      };

у мене це працює: $ scope дякую Джейсону Світту


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