AngularJS कार्यशाला - व्यवस्थापक पैनल विकास (भाग 2)

पहले भाग में , AngularJS जावास्क्रिप्ट फ्रेमवर्क पर व्यवस्थापक पैनल की मूल कार्यक्षमता को लागू किया गया था - बैकेंड से डेटा लोड करना, प्रविष्टियों को जोड़ना / बदलना। दूसरे भाग में, हम रिकॉर्ड्स को हटाते हुए टेबल और पेजिंग को लागू करने पर विचार करेंगे।


छंटाई


हम डिफ़ॉल्ट सॉर्ट क्रम को सेट करने के लिए नियंत्रकों.जेएस फ़ाइल में सूची नियंत्रक में टेबलहेड सरणी को पूरक करते हैं। 0 से अधिक संख्या - क्रमबद्ध आरोही, 0 से कम - अवरोही। संख्या मॉड्यूल कॉलम द्वारा क्रमबद्ध क्रम दिखाता है।
... $scope.tablehead = [ {name:'title', title:"", sort:-2}, {name:'category', title:"", list:$scope.categories, sort:1}, {name:'answerer', title:" ", list:$scope.answerers}, {name:'author', title:""}, {name:'created', title:""}, {name:'answered', title:""}, {name:'shown', title:""} ]; ... 

जब आप हेडर पर क्लिक करते हैं, तो सॉर्टिंग काम करना चाहिए, जिसका अर्थ है कि हम इसे कार्यक्षमता संलग्न करेंगे। AngularJS पर, यह बहुत सरल है। तालिका शीर्षक को list.html टेम्पलेट में बदलें:
 ... <thead> <tr ng-mousedown="$event.preventDefault()" onselectstart="return false"> <th ng-repeat="head in tablehead" ng-click="sortReorder(head.name,$event)" ng-class="{'sort-asc':head.sort>0,'sort-desc':head.sort<0}">{{head.title}}</th> </tr> </thead> <tbody> <tr ng-repeat="item in items | filterEx:tablehead:filter | orderByEx:tablehead:sortBy()"> ... 

और नियंत्रक के लिए छँटाई कार्य जोड़ें:
 ... $scope.sortBy = function() { var order = []; angular.forEach($scope.tablehead, function(h){ if (h.sort>0) order[h.sort-1] = h.name; if (h.sort<0) order[Math.abs(h.sort)-1] = '-'+h.name; }); return order; }; $scope.sortReorder = function(col,e) { if (e.shiftKey) { var sortIndex = 0; angular.forEach($scope.tablehead, function(el) { if (Math.abs(el.sort)>sortIndex) sortIndex = Math.abs(el.sort); }); angular.forEach($scope.tablehead, function(el) { if (el.name==col) el.sort = el.sort?-el.sort:sortIndex+1; }); } else { angular.forEach($scope.tablehead, function(el) { if (el.name==col) el.sort = el.sort>0?-1:1; else el.sort = null; }); } }; ... 

सॉर्टबाय () फ़ंक्शन को सीधे तब बुलाया जाता है जब ऑर्डरबायएक्स फ़िल्टर द्वारा सॉर्ट किया जाता है, और वांछित क्रम में कॉलम नामों को वापस करता है, एक माइनस साइन रिवर्स सॉर्टिंग को इंगित करता है। SortReorder () फ़ंक्शन को सॉर्ट करता है, शिफ़्ट कुंजी को नीचे रखने के साथ, आप एक नया कॉलम जोड़ सकते हैं, बार-बार चयनित कॉलम पर क्लिक करने से इस कॉलम का क्रम क्रम बदल जाता है।
इस कार्य में, मैं फिर से इस तथ्य पर आया कि अंतर्निहित क्रम फ़िल्टर फ़िल्टर सॉर्ट करने से पहले स्तंभों के स्रोत डेटा को लेता है, और श्रेणी और प्रतिक्रिया कॉलमों को गलत तरीके से सॉर्ट करता है। मैंने AngularJS कोड से ऑर्डरबाय फिल्टर कोड को चीर दिया और उसमें बदलाव किया। परिवर्तन महत्वहीन हैं (4 पंक्तियों को जोड़ा गया था जो आवश्यक डेटा के साथ तुलनित्र को बुलाते हैं), इसलिए मैंने इसे यहां नहीं दिया (आप गिटहब पर फ़िल्टर कोड देख सकते हैं)।

पृष्ठ पर अंक लगाना


एक महत्वपूर्ण कार्य पृष्ठों में एक बड़ी तालिका को तोड़ना है। ऐसा करने के लिए, हम ListCtrl कंट्रोलर (फ़ाइल /js/controllers.js) को पूरक करते हैं:
 ... $scope.paginator = { count: 5, // -    page: 1, pages: 1, setPages: function(itemsCount){ this.pages = Math.ceil(itemsCount/this.count); } }; $scope.items = Items.query(function(data){ $scope.paginator.setPages($scope.items.length); //    var i = 0; angular.forEach(data, function(v,k) { data[k]._id = i++; }); }); $scope.$watch('items',function() { $scope.paginator.setPages($scope.items.length); }); $scope.$watch('paginator.page',function() { if ($scope.paginator.page<1) $scope.paginator.page = 1; if ($scope.paginator.page>$scope.paginator.pages) $scope.paginator.page = $scope.paginator.pages; angular.forEach($scope.items, function(v,k) { $scope.items[k].selected = false; }); }); ... 

इस कोड में $ घड़ी () फ़ंक्शन दिलचस्प है - इसे कहा जाता है जब इसमें निर्दिष्ट किसी भी अभिव्यक्ति को बदल दिया जाता है ( $ घड़ी समारोह के बारे में अधिक )। यह समारोह के अंदर इस चर के साथ प्रयोग करना दिलचस्प था ...
कृपया ध्यान दें कि paginator.setPages () विधि को दो बार कहा जाता है - लोडिंग आइटम के कॉलबैक में और फ़ंक्शन $ वॉच ('आइटम') में। तथ्य यह है कि $ गुंजाइश.items = Item.query () एक वादा-वस्तु लौटाता है, जिसके असाइनमेंट में $ वॉच ट्रिगर होती है, लेकिन तब डेटा लोड करते समय, यह अब मौजूद नहीं है, क्योंकि वादे-ऑब्जेक्ट में आंतरिक परिवर्तन हैं।
List.html टेम्पलेट में कुछ पंक्तियाँ जोड़ें। हम तालिका श्रृंखला पुनरावृत्ति पूरक:
 ... <tr ng-repeat="item in items | filterEx:tablehead:filter | orderByEx:tablehead:sortBy() | showPage:paginator"> ... 

और तालिका के बाद पृष्ठ नियंत्रण बटन जोड़ें:
 ... <div id="table-tools"> <div class="pull-left">  {{Math.min(paginator.count,items.length)}}   {{items.length}} </div> <div class="controls input-append pull-right"> <input type="button" ng-click="paginator.page=1" class="btn btn-small" value="<<"> <input type="button" ng-click="paginator.page=paginator.page-1 || 1" class="btn btn-small" value="<"> <input ng-model="paginator.page" class="paginator-page"><span class="add-on"> {{paginator.pages}} .</span> <input type="button" ng-click="paginator.page=Math.min(paginator.page+1,paginator.pages)" class="btn btn-small" value=">"> <input type="button" ng-click="paginator.page=paginator.pages" class="btn btn-small" value=">>"> </div> <div class="clear"></div> </div> ... 

बटन हैंडलर्स में सशर्त भाव होते हैं जो पृष्ठ सीमा को सीमित करते हैं और कॉल की संख्या को $ वॉच () हैंडलर फ़ंक्शन तक कम करते हैं।
खैर, filter.js फ़ाइल में showPage फ़िल्टर कोड:
 ... .filter('showPage', function() { return function(list, paginator) { if (paginator.page<1) paginator.page = 1; if (paginator.count<1) paginator.count = 1; if (paginator.pages && paginator.page>paginator.pages) paginator.page = paginator.pages; return list.slice(paginator.count*(paginator.page-1), paginator.count*paginator.page); }; }); 

कोड काफी स्पष्ट है, मैं इसे समझाने की बात नहीं देखता।

लाइनों को हाइलाइट करें और हटाएं


बस थोड़ा सा बचा है। हम लाइनों को चुनने और हटाने के लिए कोड लिखेंगे। List.html टेम्प्लेट में (आखिरी बार), क्लिक हैंडलर जोड़कर लाइन इटरेटर को बदलें और एंट्री को हाइलाइट करने के लिए क्लास जोड़कर:
 ... <tr ng-repeat="item in items | filterEx:tablehead:filter | orderByEx:tablehead:sortBy() | showPage:paginator" ng-click="selectItem($event)" ng-class="item.selected && 'selected'"> ... 

तालिका के सामने (div.tools अनुभाग में) कुछ बटन जोड़ें:
 ... <button ng-click="deleteItem(1)" class="btn btn-danger" ng-show="selected.length==1">  </button> <button ng-click="deleteItem()" class="btn btn-danger" ng-show="selected.length>1">   ({{selected.length}})</button> ... 

ये बटन दिखाए गए हैं (एनजी-शो == सच) यदि एक या अधिक प्रविष्टियों का चयन किया जाता है।

और ListCtrl कंट्रोलर में कुछ फ़ंक्शन जोड़ें:
 ... $scope.selected = []; $scope.deleteItem = function(one) { if (one) { var _id = $scope.selected[0]; Items['delete']({id:$scope.items[_id].id}, function() { $scope.items.splice(_id,1); $scope.selected = []; }); } else { var ids = []; angular.forEach($scope.selected, function(_id) { ids.push($scope.items[_id].id); }); Items['delete']({ids:ids}, function(){ angular.forEach($scope.selected, function(_id) { $scope.items.splice(_id,1); }); $scope.selected = []; }); } }; $scope.selectItem = function(e) { if ((e.target||e.srcElement).tagName!='TD') return; var state = this.item.selected = !this.item.selected, _id = this.item._id; if (state) $scope.selected.push(_id); else angular.forEach($scope.selected, function(v,k) { if (v==_id) { $scope.selected.splice(k,1); return false; } }); }; ... 

SelectItem () फ़ंक्शन एक तत्व की चयनित संपत्ति को सेट करता है और इसकी संख्या को विशेष $ गुंजाइश में जोड़ता है। चयनित सरणी। वैसे, तत्व संख्या इसकी _id संपत्ति में है, जिसे हम बैकएंड से तत्वों को प्राप्त करते समय भरते हैं; स्वयं AngularJS इसे नहीं जोड़ता है। DeleteItem () फ़ंक्शन हटाता है, क्रमशः, $ स्कोप में सूचीबद्ध तत्व। एलेक्टेड सरणी। यह $ संसाधन ऑब्जेक्ट में निर्मित डिलीट () विधि का उपयोग करता है। (इसे एक्सप्रेशन आइटम ['डिलीट'] (), और आइटम्स.डेलीट () का उपयोग करके कहा जाता है, क्योंकि मेरी आईडीई मानती है कि डिलीट एक अंतर्निहित जावास्क्रिप्ट ऑपरेटर है, और बदसूरत एक त्रुटि दिखाता है ... लेकिन हर कोई जानता है कि वस्तुओं का मामला। आइटम === आइटम ['हटाएं]]

अन्य


मैं उन क्षणों के साथ कहानी को पूरक करूंगा जो मुख्य पाठ में शामिल नहीं थे।
1. {{घुंघराले ब्रैकेट्स}} टेम्प्लेट्स में (और फ़ंक्शंस) घोषित किए जाते हैं जिन्हें कंस्ट्रक्टर के $ स्कोप ऑब्जेक्ट के गुण के रूप में घोषित किया जाता है।
2. टेम्पलेट में वैश्विक वस्तुएं उपलब्ध नहीं हैं, उन्हें एक्सेस करने के लिए आपको स्पष्ट रूप से उन्हें एक अलग संपत्ति में असाइन करना होगा, उदाहरण के लिए, इस तरह: $ गुंजाइश। मैथ = मठ; और फिर इस तरह से टेम्पलेट का उपयोग करें: {{Math.min (ए, बी)}}।
3. यह बहुत स्पष्ट नहीं है कि किसी अन्य नियंत्रक के दायरे का उपयोग कैसे किया जाए। निश्चित रूप से आप कर सकते हैं, लेकिन मुझे अभी तक नहीं मिला है कि कैसे ...
4. यह बहुत स्पष्ट नहीं है कि कोड से नियंत्रक के दायरे का उपयोग कैसे किया जाए जो कि नियंत्रक में नहीं रखा गया है, उदाहरण के लिए, ग्राफिक लाइब्रेरी से। लेकिन आपको ऐसा करने की आवश्यकता नहीं है, क्योंकि सभी कोड नियंत्रकों में शामिल होने चाहिए ...
5. $ गुंजाइश। $ वॉच () फ़ंक्शन काम नहीं करता है जब सरणी गुण विभाजन / धक्का कार्यों और इस तरह से संसाधित होते हैं।

परिणाम


एक कार्यशील डेमो यहां उपलब्ध है: http://lexxpavlov.com/ng-admin/v2/ (केवल पढ़ने के लिए)
सूत्रों को GitHub पर देखा जा सकता है: https://github.com/lexxpavlov/angular-admin/

Source: https://habr.com/ru/post/In150321/


All Articles