본문 바로가기

프로그래밍/AngularJS

AngularJS 1.x - ngDraggable 모듈을 이용한 drag&drop 기능 활용 개발

angularJS 맛보기 개발 

  • 슬라이드 기능 UI 컴포넌트 만들기(관리기능)
    - 썸네일 등록 및 정렬
    - 썸네일 정보 :  URL, 설명
  • ngDraggale Angular 모듈을 이용한 드래그엔 드롭 순서 정렬
  • Modal 사용 
  • 해야할 일
    - 정보 저장, 정보 불러오기
  • 동작
    - 카테고리선택, 이미지 추가 및 드래그 엔 드롭 순서 정열, 이미지 클릭시 Modal Open
    - 모달 html 소스는 별 것 없음. 패스
  • ngDraggable 모듈 사용시 click이랑 같이 처리 하고 싶을 때

1
2
3
4
5
6
7
8
9
10
11
<li class="goods ng-scope" ng-repeat="info in thumnailSlideInfo.thumnailInfos track by $index">
    <img class="preview"
         tq-default-img
         src="{{info.preview}}"
         ng-click="modalThumnailInfo($index)"
         ng-drag="true"
         ng-drop="true"
         ng-drag-data="info"
         ng-drop-success="onDropComplete($index, $data, $event)">
    <figcaption class="figure-caption" style="text-align:center;">{{info.selectFile.name}}</figcaption>
</li>
cs


위 소스와 깉이 <img> 엘리먼트에 지시자로 ng-click, ng-drop-success를 사용.

!!!!!. 문제가 발생. Drag & Drop할 때, ng-click 이 동작함.
그래서 아래 소스와 같이 소스를 작성할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var isDragging = false;
 
// ngDraggable 모듈에는 드래그엔드롭(Drag&Drop)시 $rootScope의 상태값을 등록한다. 
// 이 상태값을 확인하면, 드래그 상태인지를 확인 가능.
$rootScope.$on('draggable:start'function (data) {
    isDragging = true;
});
 
$scope.modalThumnailInfo = function (index) {
    if (isDragging) isDragging = false;
    else {
        // click event 실행 
    }
};
 
cs

  • js 코드 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 
 // 카테고리별 썸네일 슬라이드 URL 링크 및 진열
 // @author jangsh
 // @date 19.01.10
 // @issue  애드사인 롤링(슬라이드) 기능
 
angular.module('Plugins.ThumnailSlideByCategoryView', ['ngDraggable'])
.controller('Plugins.ThumnailSlideByCategoryView.PluginCtrl'
    , ['$rootScope''$scope''$uibModal''$ThumnailSlideByCategoryView_locale'
        , function ($rootScope, $scope, $uibModal, $ThumnailSlideByCategoryView_locale) {
            /* variable */
            //$scope.L = $ThumnailSlideByCategoryView_locale; -- 다국어 처리
            $scope.thumnailSlideInfo = { slideType: 'Carousel2', categoryCodePath : '', thumnailInfos:[] };
            var isDragging = false;
 
            $rootScope.$on('draggable:start'function (data) {
                isDragging = true;
            });
 
            /* event */
            $scope.onDropComplete = function (index, obj, evt) {
                var otherObj = $scope.thumnailSlideInfo.thumnailInfos[index];
                var otherIndex = $scope.thumnailSlideInfo.thumnailInfos.indexOf(obj);
                $scope.thumnailSlideInfo.thumnailInfos[index] = obj;
                $scope.thumnailSlideInfo.thumnailInfos[otherIndex] = otherObj;
            }
 
            $scope.plusThumnail = function () {
                $scope.thumnailSlideInfo.thumnailInfos.push($scope.thumnailSlideInfo.thumnailInfos.length);
            }
 
 
            // 썸네일 정보 모달 뛰우기
            $scope.modalThumnailInfo = function (index) {
                if (isDragging) isDragging = false;
                else {
                    var modalInstance = $uibModal.open({
                        animation: true,
                        templateUrl: '/Areas/Plugins/Views/ThumnailSlideByCategoryView/template/ThumnailSlideByCategoryView_thumnailInfo.html',
                        controller: 'ThumnailSlideByCategoryView_thumnailInfo_Controller',
                        size: 'lg',
                        resolve: {
                            params : function () {
                                return { index: index, info: $scope.thumnailSlideInfo.thumnailInfos[index]};
                            }
                        }
                    });
                    modalInstance.result.then(function (thumnailInfo) {
                        if (_.isObject(thumnailInfo)) {
                            if (thumnailInfo.state == "delete") {
                                $scope.thumnailSlideInfo.thumnailInfos.splice(thumnailInfo.index, 1);
                            } else {
                                $scope.thumnailSlideInfo.thumnailInfos[thumnailInfo.index] = thumnailInfo;
                            }
                        }
                    }, function (result) {
                        console.log("modalInstance.result", result);
                    });
                }
            }
 
            $scope.onAdd = function () {
                $.post("ThumnailSlideByCategoryView/Add", $scope.thumnailSlideInfo.thumnailInfos).then(function () {
                    // 추가 
                });
            }
 
            $scope.getCategoryAndThumnailInfo = function (res) {
                $.post("/ThumnailSlideByCategoryView/GetInfo").then(function () {
                    // 가져오기
                })
            }
 
            /* event init */
            $scope.initScope = function () {
                // 저장된 정보 불러오기
                $scope.getCategoryAndThumnailInfo();
            };
            $scope.initScope();
        }])
.controller('ThumnailSlideByCategoryView_thumnailInfo_Controller'function ($scope, $uibModalInstance, params) {
    $scope.info = {
        selectFile: params.info.selectFile, preview: params.info.preview, linkUrl: params.info.linkUrl
        , contents: params.info.contents, index: params.index, state: params.state
    }
 
    $scope.onFileSelect = function ($files) {
        var file = $files[0];
        var reader = new FileReader();
        reader.onload = function (e) {
            $scope.info.preview = e.target.result;
        }
        reader.readAsDataURL(file);
        $scope.info.selectFile = file;
    }
 
    $scope.thumnailSave = function () {
        $scope.info.state = "save";
        $uibModalInstance.close($scope.info);
    }
 
    $scope.thumnailDelete = function () {
        $scope.info.state = "delete";
        $uibModalInstance.close($scope.info);
    }
 
    $scope.close = function () {
        $uibModalInstance.close($scope.info);
    }
})
tqAddModule('Plugins.ThumnailSlideByCategoryView');
cs


  • html 소스 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<div class="page-title">
    <h3>@(L.T("카테고리URL링크및진열"))</h3>
</div>
 
<div class="content row" ng-controller="Plugins.ThumnailSlideByCategoryView.PluginCtrl" ng-init="initScope()">
    <div class="order-list col-md-12" tq-loading="html">
        <div class="panel">
            <div class="panel-body">
                <div class="select-list-box show-grid">
                    <div class="select-list-box-title">
                        <h3>@(L.T("카테고리")) @(L.T("검색"))</h3>
                    </div>
                    <tq-category-list-box ng-model="thumnailSlideInfo.categoryCodePath" tq-category-mode="TMB" ng-change="onClick()"></tq-category-list-box>
                </div>
                <div class="panel-subtitle-area">
                    <h3>메인 노출 방식</h3>
                </div>
                <div class="tb_list table-responsive search-goods-list-panel">
                    <div class="input-group">
                        <label class="radio-inline"><input type="radio" name="optradio" ng-model="param.slideType">슬라이더 1</label>
                        <label class="radio-inline"><input type="radio" name="optradio" ng-model="param.slideType">슬라이더 2</label>
                    </div>
                </div>
                <div class="panel-subtitle-area">
                    <h3>이미지 및 URL 등록</h3>
                    <input type="button" value="등록" ng-click="onAdd()" class="form-control btn btn-success">
                    @*<input type="button" value="초기화" ng-click="onCreatePanel()" class="form-control btn btn-success">*@
                </div>
                <div class="tb_list table-responsive search-goods-list-panel">
                    <ul>
                        <li class="goods ng-scope" ng-repeat="info in thumnailSlideInfo.thumnailInfos track by $index">
                            <!-- 이미지 Drag&Drop 지시어 -->
                            <img class="preview" 
                                 tq-default-img
                                 src="{{info.preview}}"
                                 ng-click="modalThumnailInfo($index)"
                                 ng-drag="true"
                                 ng-drop="true"
                                 ng-drag-data="info"
                                 ng-drop-success="onDropComplete($index, $data, $event)">
                            <figcaption class="figure-caption" style="text-align:center;">{{info.selectFile.name}}</figcaption>
                        </li>
                        <li class="goods ng-scope">
                            <div style="display:flex; justify-content: center; align-items : center; width:200px; height:200px; ">
                                <span class="glyphicon glyphicon-plus" ng-click="plusThumnail()" style="font-size : 100px;"></span>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>
cs