Programing

AngularJS 모달 대화 상자에서 "취소"를 처리하는 패턴이 있습니까?

lottogame 2020. 11. 22. 18:52
반응형

AngularJS 모달 대화 상자에서 "취소"를 처리하는 패턴이 있습니까?


참고 : 이것은 AngularJS로 모달 대화 상자를 표시하는 것이 아닙니다.이 주제에는 많은 질문과 답변이 있습니다!

이 질문은 페이지의 모달 대화 상자에서 확인 및 취소 모두에 반응하는 방법에 관한 것입니다. 변수가 하나만있는 범위가 있다고 가정 해 보겠습니다.

$scope.description = "Oh, how I love porcupines..."

페이지에 모달 대화 상자를 제공하고 해당 대화 상자 내에서 ng-model = "description"을 사용하면 실제로 입력하는 모든 변경 내용이 설명 자체에 실시간으로 적용됩니다. 왜냐하면 그 대화를 어떻게 취소합니까?

내가 아래에서 설명하는 것을하라는 질문이 있습니다. 이에 대한 대답은 내가 생각 해낸 것과 동일한 "솔루션"입니다. AngularJS : 데이터 바인딩 된 모달- "저장"을 클릭 할 때만 변경 사항을 저장하거나 "취소"를 클릭하면 변경 사항을 잊습니다.

버튼을 클릭하여 모달을 불러 오면 뒷면의 기능으로 돌아가서 모달 관련 데이터의 임시 복사본을 만든 다음 모달을 팝업하면 어떻게하는지 알 수 있습니다. 그런 다음 "OK"(또는 "Save"등)가 임시 값을 실제 모델 값에 복사 할 수 있습니다.

main.js (발췌) :

$scope.descriptionUncommitted = $scope.description;

$scope.commitChanges = function () {
  $scope.description = $scope.descriptionUncommitted;
}

main.html (발췌) :

<input type="text" ng-model="descriptionUncommitted"/>

<button ng-click="commitChanges()">Save</button>

그 문제는 선언적이지 않다는 것입니다 ! 사실 다른 곳에서는 AngularJS와는 다릅니다. 마치 그들이 원하는 모든 변경을 할 수있는 ng-model-uncommitted = "description"이 필요하지만 다른 선언으로 트리거 할 때만 커밋됩니다. 플러그인 어딘가에 그런 것이 있습니까 아니면 AngularJS 자체가 그것을 추가합니까?

편집 : 그것을하는 다른 방법의 예가 순서가있을 수 있습니다.

main.js :

$scope.filename = "panorama.jpg";
$scope.description = "A panorama of the mountains.";

$scope.persist = function () { // Some function to hit a back end service. };

main.html :

<form>
  <input type="text" ng-model-uncommitted="filename"/>
  <input type="text" ng-model-uncommitted="description"/>

  <button ng-commit ng-click="persist()">Save</button>
  <button ng-discard>Cancel</button>
</form>

항목을 그룹화하는 방법을 모르기 때문에 주위에 양식 태그를 붙였습니다. 따라서 모두 동일한 "트랜잭션"(더 나은 단어가 부족한 경우)의 일부라는 것이 분명했습니다. 그러나 이것이 모두 자동으로 발생하고 모델 변수의 복제 된 사본이 초기 값에 사용되고 입력에 사용되고 자동으로 업데이트되고 유효성이 검사되는 등 마지막으로 폐기되거나 동일한 값으로 복사 될 수있는 방법이 필요합니다. 처음에는 사용자가 커밋하기로 결정한 경우 생성하는 데 사용되었습니다.

큰 웹 사이트에서 20 개의 모달에 대해 반복해서 작업을 수행하는 컨트롤러의 코드보다 이와 같은 것이 더 쉽지 않습니까? 아니면 내가 미쳤나?


기본적으로 angular에서 선언적이지 않은 경우 지시문 을 만듭니다 .

 .directive('shadow', function() {
  return {
    scope: {
      target: '=shadow'            
    },
    link: function(scope, el, att) {
      scope[att.shadow] = angular.copy(scope.target);

      scope.commit = function() {
        scope.target = scope[att.shadow];
      };
    }
  };

그때:

  <div shadow="data">
    <input ng-model="data">
    <button ng-click="commit()">save</button>
  </div>

그래서 data내부 shadow지침 될 것입니다 사본 원본 data. 그리고 버튼을 클릭하면 원본으로 다시 복사됩니다.

그리고 여기에 작업 예제가 있습니다 : jsbin

이 예제 이상으로 테스트하지 않았으므로 다른 경우에는 작동하지 않을 수 있지만 가능성에 대한 아이디어를 제공한다고 생각합니다.

편집하다:

문자열 대신 객체와 양식의 여러 필드가있는 또 다른 예 ( angular.copy여기에 추가 필요) : jsbin

Edit2, 각도 버전 1.2.x

변경 에 따라 input지시문 내부는 더 이상 격리 된 범위에 액세스하지 않습니다. 한 가지 대안은 scope:true데이터 사본을 보유하고 저장을 위해 상위 범위에 액세스하기 위해 분리되지 않은 하위 범위 ( )를 작성하는 것입니다.

따라서 이후 버전의 angular에서는 트릭을 수행하기 위해 약간 수정하기 전과 동일한 접근 방식입니다.

.directive('shadow', function() {
  return {
    scope: true,
    link: function(scope, el, att) {
      scope[att.shadow] = angular.copy(scope[att.shadow]);

      scope.commit = function() {
        scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);
      };
    }
  };
});

예 : jsbin

를 사용할 때의 문제 $parent는 결국 중간에 다른 범위가 있으면 중단 될 수 있다는 것입니다.


Angular 1.3 부터는 기본적으로 동일한 동작을 수행 할 수있는 ngModelOptions 지시문이 있습니다.

<form name="userForm">
    <input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'submit' }" name="userName">
    <button type="submit">save</button>
    <button type="button"  ng-click="userForm.userName.$rollbackViewValue();">cancel</button>
</form>

JSFiddle : http://jsfiddle.net/8btk5/104/


동일한 문제에 직면하고이 스레드를 통해 lazy-model정확히 작동 ng-model하지만 양식이 제출 될 때만 변경 사항을 저장 하는 지시문을 생각해 냈습니다 .

용법:

<input type="text" lazy-model="user.name">

<form>태그 로 감싸지 않으면 게으른 모델은 변경 사항을 원래 모델로 푸시해야하는시기를 알 수 없습니다.

전체 작동 데모 : http://jsfiddle.net/8btk5/3/

lazyModel 지시어 코드 :
( github에서 실제 버전을 더 잘 사용하십시오 )

app.directive('lazyModel', function($parse, $compile) {
  return {
    restrict: 'A',  
    require: '^form',
    scope: true,
    compile: function compile(elem, attr) {
        // getter and setter for original model
        var ngModelGet = $parse(attr.lazyModel);
        var ngModelSet = ngModelGet.assign;  
        // set ng-model to buffer in isolate scope
        elem.attr('ng-model', 'buffer');
        // remove lazy-model attribute to exclude recursion
        elem.removeAttr("lazy-model");
        return function postLink(scope, elem, attr) {
          // initialize buffer value as copy of original model 
          scope.buffer = ngModelGet(scope.$parent);
          // compile element with ng-model directive poining to buffer value   
          $compile(elem)(scope);
          // bind form submit to write back final value from buffer
          var form = elem.parent();
          while(form[0].tagName !== 'FORM') {
            form = form.parent();
          }
          form.bind('submit', function() {
            scope.$apply(function() {
                ngModelSet(scope.$parent, scope.buffer);
            });
         });
         form.bind('reset', function(e) {
            e.preventDefault();
            scope.$apply(function() {
                scope.buffer = ngModelGet(scope.$parent);
            });
         });
        };  
     }
  };
});

GitHub의 실제 소스 코드


당신은 이것을 지나치게 생각하는 것 같습니다. 프로세스가 매우 간단하기 때문에 플러그인이 없습니다. 모델의 깨끗한 사본을 원한다면 하나를 만들어 컨트롤러에 보관하십시오. 사용자가 취소하면 모델을 복사본으로 재설정하고 FormController. $ setPristine () 메서드를 사용하여 양식을 다시 원래 상태로 만듭니다.

//Controller:

myService.findOne({$route.current.params['id']}, function(results) {
    $scope.myModel = results;
    var backup = results;
}

//cancel
$scope.cancel = function() {
    $scope.myModel = backup;
    $scope.myForm.$setPristine();
}

그런 다음보기에서 :

<form name="myForm">

$ scope.myForm 컨트롤러를 만들려면 양식의 이름을 지정해야합니다.


또 다른 방법은 모델을 편집하기 전에 복사하고 취소시 원본을 복원하는 것입니다. 각도 컨트롤러 코드 :

//on edit, make a copy of the original model and store it on scope
function edit(model){
  //put model on scope for the cancel method to access
  $scope.modelBeingEdited = model;
  //copy from model -> scope.originalModel
  angular.copy(model,$scope.originalModel);  
}

function cancelEdit(){
  //copy from scope.original back to your model 
  angular.copy($scope.originalModel, $scope.modelBeingEdited)  
}
따라서 모달 대화 상자를 열 때 편집 함수를 호출하고 편집하려는 모델에 대한 포인터를 전달합니다. 그런 다음 모달 대화 상자가 $ scope.editingModel에 바인딩되어 있는지 확인하십시오. 취소시 취소 함수를 호출하면 원래 값이 다시 복사됩니다.

누군가에게 도움이되기를 바랍니다!


간단하게 유지하고 선언적으로 만들고 양식 태그 나 기타 항목에 의존하지 않으려 고합니다.

간단한 지시문 :

.directive("myDirective", function(){
return {
  scope: {
    item: "=myDirective"
  },
  link: function($scope){
    $scope.stateEnum = {
      view: 0, 
      edit: 1
    };

    $scope.state = $scope.stateEnum.view;

    $scope.edit = function(){
      $scope.tmp1 = $scope.item.text;
      $scope.tmp2 = $scope.item.description;
      $scope.state = $scope.stateEnum.edit;
    };

    $scope.save = function(){
      $scope.item.text = $scope.tmp1;
      $scope.item.description = $scope.tmp2;
      $scope.state = $scope.stateEnum.view;
    };

    $scope.cancel = function(){
      $scope.state = $scope.stateEnum.view;
    };
  },
  templateUrl: "viewTemplate.html"
};
})

viewTemplate.html :

<div>
  <span ng-show="state == stateEnum.view" ng-click="edit()">{{item.text}}, {{item.description}}</span>
  <div ng-show="state == stateEnum.edit"><input ng-model="tmp1" type="text"/> <input ng-model="tmp2" type="text"/><a href="javascript:void(0)" ng-click="save()">save</a> <a href="javascript:void(0)" ng-click="cancel()">cancel</a></div>
</div>

그런 다음 컨텍스트 (항목)를 설정하십시오.

<div ng-repeat="item in myItems">
  <div my-directive="item"></div>
</div>

실제 작업보기 : http://plnkr.co/edit/VqoKQoIyhtYnge2hzrFk?p=preview

참고 URL : https://stackoverflow.com/questions/16838148/is-there-a-pattern-for-dealing-with-cancel-in-angularjs-modal-dialogs

반응형