jQuery UI 스타일로 작성된 내역을 AngularJS 스타일의 개발방식으로 변형하는 방법을 알아보자
1. AngularJS 길을 가다
- jQuery에서 UI 컴포넌트를 모아 놓은 것이 jQuery UI라면 AngularJS기반으로 UI 컴포넌트를 모아 놓은 것이 AngularJS UI 이다
사실, Angular UI는 jQuery UI를 AngularJS를 가지고 확장한 것이다
- jQuery UI를 통하여 DOM을 조작하여 화면을 보여주는 것과 AngularJS를 통하여 UI를 조작하는 방법은 틀리다
- AngularJS를 사용하여 SoC(Separate Of Concern) 관심분리를 수행하여 테스트 및 모듈화가 가능해 진다
+ Controller : $scope를 통한 view와 two way binding
+ Service : view와 분리된 비즈니스 로직 구현
+ Directive : 재사용 가능 컴포넌트이며 model 값을 DOM 프러퍼티와 연결해주고, DOM 이벤트 반응하여 model 값을 업데이트한다
2. jQuery UI Plugin 방식을 보자
- datepicker에 대한 사용을 본다
<div>
Date Of Birth:
<input type="text" id="dateOfBirth">
<br>
Current user's date of birth:
<span id="dateOfBirthDisplay"></span>
</div>
- 자바스크립트 코드 : 비즈니스 로직과 DOM 조작이 합쳐져 있다. 날짜를 선택하면 해당 날짜의 값을 span에 표현함
$(function () {
var user = {
dateOfBirth: new Date(1970, 0, 1)
};
var displayValue = function () {
$("#dateOfBirthDisplay").text(new Date(user.dateOfBirth).toDateString());
};
var processChange = function() {
user.dateOfBirth = $("#dateOfBirth").datepicker("getDate");
displayValue();
};
$("#dateOfBirth").datepicker({
inline: true,
onClose: processChange,
onSelect: processChange
}
);
displayValue();
// initial display of value in input-box
$("#dateOfBirth").datepicker("setDate", user.dateOfBirth);
});
3. datepicker를 AngularJS 방식으로 SoC 분리해 보자
- 위의 jQuery 방식을 angularjs 방식의 model, controller, directive로 분리해 본다
Step 1) Model을 먼저 생각하고 Service를 만든다
Step 2) Model이 표현될 View에 대해 생각해 보고 template을 만들고, 필요하면 자동 모델 바인딩되는 Directive도 만든다.
Step 3) 각 View 를 Controller에 연결한다 (ng-view and routing, ng-controller)
- Model : user.dateOfBirth
- Directive : input 태그를 my-datepicker 태그로 만든다
- Controller : $scope를 통해 model을 제어한다
- AngularJs 의 Step1), Step 2), Step 3) 수행
// Step 1, 3) model
function DemoController($scope) {
$scope.user = {
dateOfBirth: new Date(1970, 0, 1)
}
}
// Step 2) directive in html
<div ng-app="demo" ng-controller="DemoController">
Date Of Birth:
<my-datepicker type="text" ng-model="user.dateOfBirth" />
<br>
Current user's date of birth:
<span id="dateOfBirthDisplay">{{user.dateOfBirth}}</span>
</div>
4. my-datepicker Directive 만들기
- AngularJS Directive 만들기에 따른 myDatepicker
+ compile 첫번째 phase : DOM 변경
+ compile 두번째 phase : DOM value 조작
// demo 모듈에 directive 만들기
angular.module("demo", []).directive('myDatepicker', function ($parse) {
return {
restrict: "E",
replace: true,
transclude: false,
// compile은 최초 한번 호출되고, return 되는 펑션이 link 펑션이 된다
compile: function (element, attrs) {
// Phase 1 - Compile function
// 엘러먼트의 어트리뷰트 express을 function으로 변환한다
// user.dateOfBirth에 대한 set, get이 가능토록 해준다
// attrs.ngModel === ng-model 과 같다
var modelAccessor = $parse(attrs.ngModel);
// 엘러먼트 태그를 바꾸어 준다
var html = "<input type='text' id='" + attrs.id + "' ></input>";
var newElem = $(html);
element.replaceWith(newElem);
// Phase 2 - Link function
// - onClose, onSelect를 정의한다
// - 이벤트 발생시 콜백을 정의한다
// - 값이 변경되었을 때 Angular Context로 들어가서 watch가 불리고 최종적으로 값을 변경한다
return function (scope, element, attrs, controller) {
// jQuery 이벤트 콜백 펑션이 호출되면 $apply를 호출하여 Angular Context가 적용되어 $watch가 자동 호출토록 한다
var processChange = function () {
var date = new Date(element.datepicker("getDate"));
// HTML element 값이 변경되었음을 $watch가 호출되도록 trigger 해주는 콜백펑션을 등록한다
scope.$apply(function (scope) {
// Change bound variable
modelAccessor.assign(scope, date);
});
};
// jQuery의 이벤트 콜백을 등록한다
element.datepicker({
inline: true,
onClose: processChange,
onSelect: processChange
});
// scope.$apply안엣 modelAccessor의 값이 변경되면 datepicker 의 setDate를 호출한다
scope.$watch(modelAccessor, function (val) {
var date = new Date(val);
element.datepicker("setDate", date);
});
};
}
};
});
<참조>
'HTML5, CSS3 > jQuery' 카테고리의 다른 글
[Slide Menu] jQuery 또는 Angular.js 기반 Slide Navigation (0) | 2013.11.30 |
---|---|
[jQueryUI] jqGrid 사용하기 - 2 (0) | 2013.11.12 |
[jQueryUI] 기본 개념 및 사용하기 - 1 (0) | 2013.11.12 |
[구글] 10가지 디자인 원칙 (0) | 2013.06.03 |
[jQuery] stopPropagation, preventDefault, return false 간의 차이점 (0) | 2013.03.20 |