Angular UI 모달의 범위 문제


80

각도 UI 모달의 범위를 이해 / 사용하는 데 문제가 있습니다.

여기에서 즉시 명확하지는 않지만 모듈과 모든 것이 올바르게 설정되어 있지만 (내가 말할 수있는 한) 특히 이러한 코드 샘플에서 버그를 찾습니다.

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>

그래서 내 질문은 : 왜 범위가 UI에 이중 바인딩되지 않습니까? 왜 this사용자 정의 값이 있지만 $scope그렇지 않습니까?

ng-controller="AppCreateCtrl"create.html에서 body div에 추가하려고했지만 "Unknown provider : $ modalInstanceProvider <-$ modalInstance"라는 오류가 발생했습니다.

이 시점에서, 내 유일한 옵션은 함께 객체를 다시 전달하는 것입니다 this.namethis.groupType사용하는 대신 $scope,하지만 그건 잘못된 생각한다.


여기에 좋은 모달 범위 토론 : github.com/mgcrea/angular-strap/issues/14
steampowered

답변:


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

이 답변은 현재 구현이므로 여기에서 작업을 수행하려는 사람들에게 더 유용 할 것이기 때문에이 답변을 수락하고 있습니다. Angular UI의 최신 (~ 0.12) 버전을 사용하지 않는 경우 전체 스레드를 읽어보세요.
coblr

범위가 설정되어 있으면 상태가 변경된 경우 $ modalStack으로 모달을 닫을 수없는 것 같습니다.
phazei

안녕하세요, 이것은 잠시 동안 내 문제를 해결했지만 모달 / 대화 상자를 닫을 때 이상한 점을 발견하고 내용이 변경되고 범위 개체에서 무언가를 엉망으로 만드는 것처럼 보였습니다. 범위 추가 : $ scope, preserveScope : true // <-중요한 도움이되었습니다! 이유는 확실하지 않지만 material.angularjs.org/latest/api/service/… 에서 찾았습니다. 편집 : 이유를 알아 냈습니다. 범위를 설정할 때 : 대화 상자의 경우 "reservScope가 true로 설정되지 않은 경우 하단 시트가 제거되면이 범위가 삭제됩니다."대화 상자를 닫습니다.
Max

내 컨트롤러에서 vm = this를 사용하고 있습니다. $ scope를 사용하지 않습니다. 그러면 범위에 무엇을 할당해야합니까?
Ankit Prajapati 2018

66

중첩 된 범위가 관련된 경우 <input>s를 범위의 멤버에 직접 바인딩하지 마십시오 .

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

최소한 한 단계 더 깊게 바인딩하십시오.

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

그 이유는 범위가 프로토 타입 적으로 부모 범위를 상속하기 때문입니다. 따라서 첫 번째 수준 구성원을 설정할 때 부모에 영향을주지 않고 자식 범위에 직접 설정됩니다. 반대로 중첩 된 필드 ( 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 as my"를 수행 한 다음 my.someVar와 같은 ng-model을 참조합니다.
Ryan Q

2
@Nikos Paraskevopoulos, "form.name"은 무엇을 의미합니까? 제공된 코드에 전혀 언급되지 않았습니다!
ŁukaszBachman

7

2014 년 11 월 업데이트 :

실제로 코드는 ui-bootstrap 0.12.0으로 업그레이드 한 후에 작동합니다. 매개자 범위는 그래서 더 이상 필요한 컨트롤러의 범위와 병합 $parent또는 form.물건.

0.12.0 이전 :

모달은 transclusion을 사용하여 내용을 삽입합니다. 덕분 ngFormname속성 별로 범위를 제어 할 수 있습니다 . 따라서 transcluded 범위를 벗어나려면 다음과 같이 양식을 수정하십시오.

<form name="$parent">

또는

<form name="$parent.myFormData">

모델 데이터는 컨트롤러 범위에서 사용할 수 있습니다.


명확하게 말하면, 호출하는 컨트롤러의 범위를 $modal모달에 할당 된 컨트롤러에서 사용할 수 있어야한다는 말입니까?
Jason Swett

아니요, 문제는 모달 인스턴스 컨트롤러조차도 양식에 쉽게 액세스 할 수 없다는 것입니다. 모달을 여는 컨트롤러에 액세스하려면 scope:$scope$ modal.open params 맵에 넣으십시오 .
gertas

Angular UI를 의미합니까? UI 부트 스트랩과 다른가요?
Noah

1
$scope.open = function () {

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

      };

그것은 나를 위해 작동합니다 범위 : $ scope 감사합니다 제이슨 Swett


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.