AngularJS 및 content편집 가능한 양방향 바인딩이 예상대로 작동하지 않음
다음 예제에서는 초기 렌더링 값이 다음과 같은 이유를 설명합니다.{{ person.name }}
보다는David
어떻게 해결할 수 있을까요?
HTML:
<body ng-controller="MyCtrl">
<div contenteditable="true" ng-model="person.name">{{ person.name }}</div>
<pre ng-bind="person.name"></pre>
</body>
JS:
app.controller('MyCtrl', function($scope) {
$scope.person = {name: 'David'};
});
app.directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
// view -> model
element.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(element.html());
});
});
// model -> view
ctrl.$render = function() {
element.html(ctrl.$viewValue);
};
// load init value from DOM
ctrl.$setViewValue(element.html());
}
};
});
보간 작업이 아직 완료되지 않은 상태에서 뷰 값을 업데이트하는 것이 문제입니다.
그래서 제거하다
// load init value from DOM
ctrl.$setViewValue(element.html());
또는 로 대체한다.
ctrl.$render();
이 문제를 해결합니다.
단답
다음 라인을 사용하여 DOM에서 모델을 초기화합니다.
ctrl.$setViewValue(element.html());
컨트롤러에서 값을 설정하기 때문에 DOM에서 초기화할 필요는 없습니다.이 초기화 라인을 삭제하기만 하면 됩니다.
장황한 답변(아마도 다른 질문에 대한 답변)
이것은 실제로 알려진 문제입니다.https://github.com/angular/angular.js/issues/528
공식 문서의 예를 참조하십시오.
HTML:
<!doctype html>
<html ng-app="customControl">
<head>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<form name="myForm">
<div contenteditable
name="myWidget" ng-model="userContent"
strip-br="true"
required>Change me!</div>
<span ng-show="myForm.myWidget.$error.required">Required!</span>
<hr>
<textarea ng-model="userContent"></textarea>
</form>
</body>
</html>
JavaScript:
angular.module('customControl', []).
directive('contenteditable', function() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if(!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
element.on('blur keyup change', function() {
scope.$apply(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if( attrs.stripBr && html == '<br>' ) {
html = '';
}
ngModel.$setViewValue(html);
}
}
};
});
커스텀 디렉티브에 대한 이해는 다음과 같습니다.
아래 코드는 양방향 바인딩의 기본 개요입니다.
여기에서도 볼 수 있습니다.
http://plnkr.co/edit/8dhZw5W1JyPFUiY7sXjo
<!doctype html>
<html ng-app="customCtrl">
<head>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular.min.js"></script>
<script>
angular.module("customCtrl", []) //[] for setter
.directive("contenteditable", function () {
return {
restrict: "A", //A for Attribute, E for Element, C for Class & M for comment
require: "ngModel", //requiring ngModel to bind 2 ways.
link: linkFunc
}
//----------------------------------------------------------------------//
function linkFunc(scope, element, attributes,ngModelController) {
// From Html to View Model
// Attaching an event handler to trigger the View Model Update.
// Using scope.$apply to update View Model with a function as an
// argument that takes Value from the Html Page and update it on View Model
element.on("keyup blur change", function () {
scope.$apply(updateViewModel)
})
function updateViewModel() {
var htmlValue = element.text()
ngModelController.$setViewValue(htmlValue)
}
// from View Model to Html
// render method of Model Controller takes a function defining how
// to update the Html. Function gets the current value in the View Model
// with $viewValue property of Model Controller and I used element text method
// to update the Html just as we do in normal jQuery.
ngModelController.$render = updateHtml
function updateHtml() {
var viewModelValue = ngModelController.$viewValue
// if viewModelValue is change internally, and if it is
// undefined, it won't update the html. That's why "" is used.
viewModelValue = viewModelValue ? viewModelValue : ""
element.text(viewModelValue)
}
// General Notes:- ngModelController is a connection between backend View Model and the
// front end Html. So we can use $viewValue and $setViewValue property to view backend
// value and set backend value. For taking and setting Frontend Html Value, Element would suffice.
}
})
</script>
</head>
<body>
<form name="myForm">
<label>Enter some text!!</label>
<div contenteditable
name="myWidget" ng-model="userContent"
style="border: 1px solid lightgrey"></div>
<hr>
<textarea placeholder="Enter some text!!" ng-model="userContent"></textarea>
</form>
</body>
</html>
호프야, 그게 밖에 있는 누군가를 도울 수 있어!!!
이 angularjs 디렉티브 https://github.com/clofus/angular-inputnlabel 를 체크해 주세요.
스코프가 있는 경우 @Vanaun 코드를 사용하면 문제가 발생할 수 있습니다.$190은 이미 진행 중입니다.이 경우 대신 $timeout을 사용하여 문제를 해결합니다.
HTML:
<!doctype html>
<html ng-app="customControl">
<head>
<script src="http://code.angularjs.org/1.2.0-rc.2/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<form name="myForm">
<div contenteditable
name="myWidget" ng-model="userContent"
strip-br="true"
required>Change me!</div>
<span ng-show="myForm.myWidget.$error.required">Required!</span>
<hr>
<textarea ng-model="userContent"></textarea>
</form>
</body>
</html>
JavaScript:
angular.module('customControl', []).
directive('contenteditable', function($timeout) {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if(!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
element.on('blur keyup change', function() {
$timeout(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if( attrs.stripBr && html == '<br>' ) {
html = '';
}
ngModel.$setViewValue(html);
}
}
};
});
동작 예: Plunkr
언급URL : https://stackoverflow.com/questions/14561676/angularjs-and-contenteditable-two-way-binding-doesnt-work-as-expected
'bestsource' 카테고리의 다른 글
npx create-react-app을 사용하여 react를 설치할 수 없습니다. (0) | 2023.03.05 |
---|---|
스프링 부트 - 생성되는 연결 수 제한 (0) | 2023.03.05 |
Wordpress 썸네일 생성에 연결하는 방법 (0) | 2023.03.05 |
Apache 웹 서버에 React App을 배포하는 방법 (0) | 2023.03.05 |
Retrofit에서 Dynamic JSON을 처리하는 방법 (0) | 2023.03.05 |