Các vấn đề về phạm vi với phương thức Angular UI


80

Tôi đang gặp khó khăn khi hiểu / sử dụng phạm vi cho phương thức giao diện người dùng góc cạnh.

Mặc dù không rõ ràng ngay lập tức ở đây, nhưng tôi có các mô-đun và mọi thứ được thiết lập chính xác (theo như tôi có thể nói), nhưng những mẫu mã này cụ thể là nơi tôi tìm thấy lỗi.

index.html (phần quan trọng của nó)

<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 (một lần nữa, phần quan trọng)

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 (toàn bộ)

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

Vì vậy, câu hỏi của tôi là: tại sao phạm vi không bị ràng buộc kép với giao diện người dùng? và tại sao thiscó các giá trị tùy chỉnh, nhưng $scopekhông có?

Tôi đã cố gắng thêm ng-controller="AppCreateCtrl"vào body div trong create.html, nhưng điều đó đã gây ra lỗi: "Nhà cung cấp không xác định: $ modalInstanceProvider <- $ modalInstance" nên không may mắn ở đó.

Tại thời điểm này, lựa chọn duy nhất của tôi là trả lại một đối tượng bằng this.namethis.groupTypethay vì sử dụng $scope, nhưng điều đó cảm thấy sai.


Thảo luận về phạm vi phương thức tốt ở đây: github.com/mgcrea/angular-strap/issues/14
steampowered

Câu trả lời:


60

Tôi phải làm việc như thế này:

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

Không có tên biểu mẫu, không $parent. Tôi đang sử dụng AngularUI Bootstrap phiên bản 0.12.1.

Tôi đã nghiêng về giải pháp này bởi điều này .


Đây là một giải pháp tốt hơn nhiều. Sạch hơn nhiều. Gần đây, chúng tôi vừa mới nâng cấp lên 0.12.1 và hiện đang sửa các thay đổi vi phạm mà nó đã giới thiệu. Tôi có thể thêm điều này vào danh sách. Cảm ơn!!
coblr

Tôi chấp nhận câu trả lời này vì đây là cách triển khai hiện tại và sẽ hữu ích hơn cho những người cuối cùng ở đây đang cố gắng để mọi thứ hoạt động. Vui lòng đọc toàn bộ chủ đề trừ khi bạn đang sử dụng phiên bản Angular UI mới nhất (~ 0.12).
coblr

Các phương thức dường như không được closable với $ modalStack nếu nhà nước đã thay đổi nếu phạm vi được thiết lập
phazei

Xin chào, điều này đã giải quyết vấn đề của tôi trong một thời gian, nhưng nhận thấy một điều kỳ lạ khi đóng phương thức / hộp thoại, nội dung đang thay đổi và có vẻ như nó gây rối với một cái gì đó trên đối tượng phạm vi. thêm phạm vi: $ scope, keepScope: true // <- quan trọng bằng cách nào đó đã giúp! không rõ lý do tại sao, nhưng tìm thấy nó trên material.angularjs.org/latest/api/service/… Chỉnh sửa: Tôi đã tìm ra lý do. khi bạn đặt phạm vi: cho hộp thoại, và sau đó đóng hộp thoại "Phạm vi này sẽ bị phá hủy khi trang tính dưới cùng bị loại bỏ trừ khi duy trì được đặt thành true."
Tối đa

Trong bộ điều khiển của tôi, tôi đang sử dụng vm = this. Tôi không sử dụng $ scope. Sau đó, những gì tôi nên gán cho phạm vi?
Ankit Prajapati

66

Khi các phạm vi lồng nhau có liên quan, không ràng buộc <input>trực tiếp các thành viên của phạm vi:

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

Ràng buộc chúng ở mức sâu hơn ít nhất:

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

Lý do là phạm vi kế thừa nguyên mẫu phạm vi cha của chúng. Vì vậy, khi thiết lập thành viên cấp 1, những thành viên này được đặt trực tiếp trên phạm vi con, không ảnh hưởng đến phụ huynh. Ngược lại với điều đó, khi liên kết với các trường lồng nhau ( form.name), thành viên formđược đọc từ phạm vi cha, vì vậy việc truy cập thuộc nametính sẽ truy cập đúng mục tiêu.

Đọc mô tả chi tiết hơn ở đây .


14
Mặc dù việc thay đổi nó thành 'form.name' không làm được gì, nhưng việc thay đổi nó thành ng-model = "$ parent.name" đã khắc phục được sự cố. Cảm ơn! (. và cảm ơn cho đọc tài liệu cũng đã không nhìn thấy cái này được nêu ra.)
coblr

1
Nếu bạn sử dụng controller ascú pháp thì bạn sẽ không gặp phải các vấn đề về phạm vi lồng nhau như thế này
cướp

Là gì controller as cú pháp?
adrianboimvaser

1
Xem docs.angularjs.org/api/ng.directive:ngController . Về cơ bản làm ng-controller = "MyCtrl như tôi", sau đó tham khảo một ng-mô hình như my.someVar
Ryan Q

2
@Nikos Paraskevopoulos, "form.name" đại diện cho điều gì? Nó không được đề cập trong mã được cung cấp cả!
ŁukaszBachman

7

Cập nhật tháng 11 năm 2014 :

Trên thực tế, mã của bạn sẽ hoạt động sau khi nâng cấp lên ui-bootstrap 0.12.0. Phạm vi đã bao gồm được hợp nhất với phạm vi của bộ điều khiển nên không cần thêm $parenthoặc nhiều form.thứ nữa.

Trước 0.12.0 :

Phương thức sử dụng phép ghép để chèn nội dung của nó. Nhờ ngFormbạn có thể kiểm soát phạm vi theo namethuộc tính. Vì vậy, để thoát khỏi phạm vi bị loại trừ, chỉ cần sửa đổi biểu mẫu theo cách này:

<form name="$parent">

hoặc là

<form name="$parent.myFormData">

Dữ liệu mô hình sẽ có sẵn trong phạm vi bộ điều khiển.


Để rõ ràng hơn, bạn đang nói rằng phạm vi của bộ điều khiển bên trong mà bạn đang gọi $modalphải có sẵn cho bộ điều khiển được gán cho phương thức?
Jason Swett

Không, vấn đề là ngay cả bộ điều khiển phiên bản phương thức cũng không dễ dàng truy cập cho các biểu mẫu. Để truy cập bộ điều khiển mở phương thức, chỉ cần đưa scope:$scopevào bản đồ $ modal.open params.
gertas

Bạn có nghĩa là Angular UI? Điều đó có khác với UI Bootstrap không?
Noah

1
$scope.open = function () {

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

      };

nó hoạt động đối với tôi phạm vi: $ scope cảm ơn bạn Jason Swett


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.