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);
});
});
};
}
};
});
당신은 이것을 지나치게 생각하는 것 같습니다. 프로세스가 매우 간단하기 때문에 플러그인이 없습니다. 모델의 깨끗한 사본을 원한다면 하나를 만들어 컨트롤러에 보관하십시오. 사용자가 취소하면 모델을 복사본으로 재설정하고 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)
}
누군가에게 도움이되기를 바랍니다!
간단하게 유지하고 선언적으로 만들고 양식 태그 나 기타 항목에 의존하지 않으려 고합니다.
간단한 지시문 :
.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
'Programing' 카테고리의 다른 글
CORS : 자격 증명 모드는 '포함'입니다. (0) | 2020.11.22 |
---|---|
RESTful 방식으로 유효성 검사 API를 노출하는 방법은 무엇입니까? (0) | 2020.11.22 |
장치 드라이버 작성을 시작하려면 어떻게해야합니까? (0) | 2020.11.22 |
데이터베이스 디자인 : 계정 잔액 계산 (0) | 2020.11.22 |
Android AudioRecord 클래스-라이브 마이크 오디오를 빠르게 처리하고 콜백 기능을 설정합니다. (0) | 2020.11.22 |