為期半個月的項目實踐開發,已完整告一段落,團隊小組獲得第一名,辛苦總算沒有白費,想起有一天晚上,整個小組的人,聯調到12點才從公司回去,真是心酸。這裡總結一下,項目過程中遇到的問題 和感悟。哈哈,放張集體照。嘿嘿,項目所有的不同的team的小伙伴,一群優秀的小伙伴(大多都來自高校211,985)麽麽 ...
為期半個月的項目實踐開發,已完整告一段落,團隊小組獲得第一名,辛苦總算沒有白費,想起有一天晚上,整個小組的人,聯調到12點才從公司回去,真是心酸。這裡總結一下,項目過程中遇到的問題
和感悟。哈哈,放張集體照。嘿嘿,項目所有的不同的team的小伙伴,一群優秀的小伙伴(大多都來自高校211,985)麽麽噠.下麵介紹下我們組的產品和問題。
項目已放在github上:https://github.com/foreverjiangting/myApp/tree/master/myApp/myApp
一:項目效果展示
先展示一下我們做的產品,主要是做一個投票的APP,包括用戶登錄,註冊,答卷,查看答卷詳情,排行榜等功能。後臺可創建問卷,分發問卷,增加單選題和多選題,創建問卷題目,我這邊前端的app將其顯
示出來。基本上可以滿足需求,但還有很多不完善的地方。
二:製作功能問題總結
先看下核心功能,用戶進行單選,多選後,將保存用戶的答案,傳遞後後端,然後在展示詳情裡面將用戶的答案進行展示出來。這裡先貼下代碼。
<ion-slide-box show-pager="false" on-slide-changed="onSlideChanged(index)" active-slide="currentIndex"> <ion-slide class="set-container" ng-repeat="value in objData" repeat-done="repeatDone()" > <div class="swiper-slide swiper-slide-duplicate swiper-slide-active" style="width: 349px; margin-right: 30px;"> <div class="scores" > <h3>{{data.title}}</h3> <div class="f"><span id="span-text">{{$index+1}}</span>{{value.title}}</div> <div class="choose"> <div class="input" ng-repeat="(key,value2) in value.items"> <label for="26"> <input type="radio" name="radio{{$parent.$index}}" class="radio" value="{{key}}" ng-model= "selectedValue.radioData[$parent.$index]"> <span >{{value2}}</span> </label> </div> </div> </div> </div> </ion-slide>
這裡有幾個問題,由於是公用同一個模板,每一個ion-slide就是一頁,且一頁下麵有多個選項。問題如下:
1.如何區分不同個ion-slide下的radio ?貼下代碼,只要給name添加就可以。$parent.$index即可
<input type="radio" name="radio{{$parent.$index}}" class="radio"
2.如何獲取用戶選擇的當前頁的答案?使用ng-model即可,將用戶選擇的答案分別存在一個數組裡面。
ng-model= "selectedValue.radioData[$parent.$index]">
基本上也沒啥難點,就是方法要知道。用戶填寫答案完成後,進行保存,我們需要獲取用戶提交的所有答案。看下代碼。
$scope.submitData = {}; //用戶提交完畢,當前的問卷被提交,修改其狀態為已完成。可在已完成的欄目進行查看 $scope.submitSuccess = function(){ var radioJsonData = $scope.selectedValue.radioData; var radioObject = []; for(var k in radioJsonData){ radioObject.push(radioJsonData[k]); } console.log('3333') console.log(radioObject); console.log(radioJsonData) //獲取radioData的長度,判斷用戶選擇的數據是否完整 var radioLength = 0; var getRadioLength = function(radioJsonData){ for(var item in radioJsonData){ radioLength++; } return radioLength; } if(getRadioLength(radioJsonData) == $scope.serveLength-1){ var submitData = window._single = { "single":radioObject }; var submitId = window._id = { "id" : $stateParams.timuId } console.log(JSON.stringify(submitData)); var alertPopup = $ionicPopup.alert({ title: '保存成功', template: '您的單選題已完成,請繼續答題!' }); alertPopup.then(function(res) { history.go(-1); }); } else{ var alertPopup = $ionicPopup.alert({ title: '提交失敗', template: '您的問卷未完成,請返回查看詳情!' }); alertPopup.then(function(res) { console.log('提交失敗'); }); } };
3.再來看下多選題,跟單選題有點區別。
<ion-slide-box show-pager="false" on-slide-changed="onSlideChanged(index)" active-slide="currentIndex"> <ion-slide class="set-container" ng-repeat="value in objData" repeat-done="repeatDone()" > <div class="swiper-slide swiper-slide-duplicate swiper-slide-active" style="width: 349px; margin-right: 30px;"> <div class="scores"> <h3>{{data.title}}</h3> <div class="f"><span id="span-text">{{$index+1}}</span>{{value.title}}</div> <div class="choose" > <div class="input" ng-repeat="(key,value2) in value.items"> <label for="26"> <input type="checkbox" name="radio{{$parent.$index}}" class="radio" ng-model = "selected[$parent.$index][$index]" > <span style="margin-left: 30px;">{{value2}}</span> </label> </div> </div> </div> </div> </ion-slide>
問題如下:
1.如何在多選裡面選中多個答案呢?
ng-model = "selected[$parent.$index][$index]"
這種方法是最簡單的,雖然不是我們要的,但之後再做一下解析即可。數組裡面的數據是這樣子的。因為我們只需要保存用戶選擇的答案的當前題目的index,保存以1,2,3,4的形式保存即可。
看下解析的代碼如下:
$scope.nextSlide = function(){ var slideIndex = $ionicSlideBoxDelegate.currentIndex(); $scope.connectedData = $scope.selected.map(function(item){ var connectSelected = []; for(var i in item){ if(item[i]){ connectSelected.push(parseInt(i)+1); } } return connectSelected.join('/'); //進行解析,以/進行分割 }) if( $scope.connectedData == null){ var alertPopup = $ionicPopup.alert({ template: '您還沒有選擇,請選擇答案!' }); }else if( $scope.connectedData[slideIndex] == null && slideIndex != $scope.serveLength-1 ){ var alertPopup = $ionicPopup.alert({ template: '您還沒有選擇,請選擇答案!' }); return true; }else { $ionicSlideBoxDelegate.next(); } return ; console.log('test:'+JSON.stringify( $scope.connectedData)); //$ionicSlideBoxDelegate.next(); };
3.既然單選題和多選題都有答案了,現在就是提交用戶答案了。解決不同controller之間的數據通信,本來之前用的$rootscope,不知道為什麼不行,後來學霸告訴我直接
存在window下麵。於是簡單粗暴的解決了問題。
先看下代碼吧,我們前端需要提交給後端數據包括問卷的ID,單選題答案,多選題答案。下麵是提交的代碼。
.controller('chooseCtrl',['$scope','$ionicPopup', '$timeout', '$stateParams','$http','$ionicScrollDelegate','$location' ,function($scope,$ionicPopup, $timeout, $stateParams,$http,$ionicScrollDelegate,$location){ $scope.jump = function(url){ window.location = url; } $scope.chooseId = $stateParams.timuId; //獲取問卷的Id console.log( $scope.chooseId); var submitData = { "id" : $scope.chooseId } var objData = []; //剛開始渲染數據,獲取整個問卷的data,單選存在一個數組,多選存在一個數組 $http({ // url : "../data/api.json", url : "http://10.32.33.4:8080/ivotel-management/questionnaire/selectQuestionnaireDetail", method : "get", params: submitData, headers: { 'Content-Type': 'application/json;charset=UTF-8' } }).success(function(data) { var arr =data.questionnaireQuestionList; //進行解析 var singleData = [] ; var mutilData = []; for(var i=0;i<arr.length;i++){ objData[i] = arr[i].responseQuestion; } // console.log(JSON.stringify(objData)); //獲取所有的題目對象 for(var i in objData){ if(objData[i].questiontype == 1){ singleData.push(objData[i]); }else if(objData[i].questiontype == 2){ mutilData.push(objData[i]); } } window._singleData = singleData; window._singleData_length = singleData.length; window._mutilData = mutilData; window._mutilData_length = mutilData.length; window.totalQuestionData = data ; //console.log(JSON.stringify(singleData)); //console.log(JSON.stringify(mutilData)); $scope.data = data; $scope.serveData = data.questionnaireQuestionList[0].qqid; }).error(function(){ console.log('error'); }); //用戶填寫完成後,將用戶答案保存,並一起傳遞給後端 $scope.submit = function(){ if(window._multi == null){ window._multi = []; } var submitTotalData = [ window._id , window._single , window._multi ] ; $http({ url : "http://10.32.33.4:8080/ivotel-examuser/questionnairePapers/Submit", method : "post", data : submitTotalData, headers: { 'Content-Type': 'application/json;charset=UTF-8' }, withCredentials :true }).success(function(data) { console.log('success'); }).error(function(){ console.log('error'); }); var alertPopup = $ionicPopup.alert({ title: '提交成功', template: '您的問卷已完成,請返回查看詳情!' }); alertPopup.then(function(res) { history.go(-1); }); console.log('test: ' + JSON.stringify( submitTotalData)); } }])
輸出時用戶提交的所有答案格式如下:
將不同的controller裡面的值,分別存在window下麵的某一個屬性下麵,即可在全局中進行使用。
4.OK ,既然答案都已經保存好啦,現在,我們需要將答案展示出來。在詳情頁面列表中。
看下後端傳給我們的數據格式如下:
{ "answer": { //單選 "1": "4", //第一題,用戶選擇第四個答案 "2": "1", //第二題,用戶選擇第一個答案 "3":"3" //第三題,用戶選擇第三個答案 }, "multi": { //多選 "4": "1/2/3", //第四題,用戶選擇1,2,3答案 "5": "1/3/4", //第五題,用戶選擇1,3,4答案 "6": "1/3/4" //第六題,用戶選擇1,3,4答案 } }
看下效果圖,我們主要是做兩件事,1.進行解析,將用戶的答案,呈現出來。2.根據答案,選中用戶當前的radio的狀態。
這裡直接貼下代碼,解析的過程都在代碼中。比較繁瑣。
關於單選的話,根絕單選直接選中當前的radio,比較好說,直接使用下麵的方法即可:
<ion-slide class="set-container" ng-repeat="value in singleData" repeat-done="repeatDone()" > <div class="swiper-slide swiper-slide-duplicate swiper-slide-active" style="width: 349px; margin-right: 30px;"> <div class="scores" > <h3>{{data.title}}</h3> <div class="f"><span id="span-text">{{$index+1}}</span>{{value.title}}</div> <div class="choose"> <div class="input" ng-repeat="(key,value2) in value.items"> <label for="26"> <input type="radio" name="radio{{$parent.$index}}" class="radio" value="{{value2}}" ng-checked="$index == selectedIndex-1"> <span >{{value2}}</span> </label> </div> </div> </div> </div> </ion-slide>
即直接使用下麵的方法:ng-checked = "$index == selectedIndex -1"即可.
ng-checked="$index == selectedIndex-1">
這裡解析的代碼也貼一下:
.controller('listItemCtrl',['$scope','$ionicPopup', '$timeout', '$stateParams','$http','$ionicScrollDelegate','$location' ,'$ionicSlideBoxDelegate','$ionicHistory', function($scope,$ionicPopup, $timeout,$stateParams,$http,$ionicScrollDelegate,$location,$ionicSlideBoxDelegate,$ionicHistory){ // $ionicHistory.nextViewOptions({ // disableBack: true // }); $scope.repeatDone = function() { $ionicSlideBoxDelegate.update(); }; var objData = []; $scope.selectedValue = {}; $scope.radioData = []; $scope.wenjuanId = $stateParams.timuId; //獲取問卷的Id console.log('問卷Id:' + $scope.wenjuanId); var submitData = { "id" : $scope.wenjuanId } $scope.serveData = 0; $scope.objData = null; $scope.jsonRadio = []; $scope.newJsonData = []; //根據對應的題目索引,得到正確的題目 $scope.newMulitJsonData = []; $scope.currentIndex = 0; $scope.answerData = null; //所有的單選題的答案 $scope.answerMutleData = null; $scope.jsonItemData = null; $scope.selectedIndex = 0; $scope.answerArray = []; $scope.singleData = []; //所有的單選題 $scope.multiData = []; $scope.serveLength = 0; $scope.selectedMulitIndex = 0; $scope.chooseMulitData = []; $scope.single_length = 0; $scope.muiteKey = 0; $scope.arrData = []; $http({ url : "../data/doing.json", //url : "http://10.32.33.4:8080/ivotel-examuser/questionnairePapers/PaperDetail", method : "get", params: submitData, headers: { 'Content-Type': 'application/json;charset=UTF-8' }, withCredentials :true }).success(function(data) { $scope.answerData = data.answer; console.log($scope.answerData); //得到用戶選擇的答案 {1: "1", 2: "2"} var arr = data.questionnaireTemp.questionnaireQuestionList; //進行解析 for(var i=0; i< arr.length;i++){ //獲取所有的題目對象 objData[i] = arr[i].responseQuestion; } $scope.data = data; $scope.objData = objData; $scope.serveLength = objData.length; //console.log( $scope.serveLength) //console.log(JSON.stringify( $scope.objData)); for(var i in objData){ //將單選題 和 多選題分別存在不同的數組裡面 if(objData[i].questiontype == 1){ $scope.singleData.push(objData[i]); $scope.single_length = $scope.singleData.length -1 ; }else if(objData[i].questiontype == 2){ $scope.multiData.push(objData[i]); } } //如果為單選的話,為 $scope.singleData for(var i in $scope.answerData){ //i為key值開始 if(i == ($ionicSlideBoxDelegate.currentIndex()+1)){ $scope.newJsonData.push($scope.singleData[i-1].items[($scope.answerData[i])]); } } $scope.selectedIndex = parseInt($scope.answerData[$ionicSlideBoxDelegate.currentIndex()+1]) ; console.log('selectedIndex : ' +$scope.selectedIndex) console.log('jsonNewData:' + JSON.stringify( $scope.newJsonData)); //如果為多選的話,為$scope.multiData $scope.answerMutleData = data.multi; console.log( JSON.stringify($scope.answerMutleData)); //對數組進行解析 var temp = 0; for(var i in $scope.answerMutleData){ //i為3 var arr = $scope.answerMutleData[i].split('/'); $scope.arrData = arr ; for (var i in arr){ // $scope.muiteKey = arr[i]; //獲取key值,並賦值給全局變數 } // $scope.muiteKey = arr[$ionicSlideBoxDelegate.currentIndex()] console.log('arr : ' + JSON.stringify(arr)); //[1,2,3] console.log('key: ' + JSON.stringify($scope.arrData)); for(var j=0;j < arr.length; j++){ console.log('test: ' +temp ); if(i == ($ionicSlideBoxDelegate.currentIndex()+1)){ $scope.newMulitJsonData.push($scope.multiData[temp].items[(arr[j])]); } } temp++; console.log('arrDate:' + JSON.stringify($scope.arrData)); } console.log($scope.newMulitJsonData); //所有的單選全部展示完成後,開始展示所有的多選 $scope.selectedMulitIndex = parseInt($scope.answerMutleData[$ionicSlideBoxDelegate.currentIndex()+1]) ; $scope.muiteKey = parseInt($scope.answerMutleData[$ionicSlideBoxDelegate.currentIndex()+1]) ; console.log( $scope.selectedMulitIndex); }).error(function(){ console.log('error'); }); $scope.jsonItemData = []; var osingMes = document.getElementById('singleMessage'); var omulit = document.getElementById('muiltMessage'); $scope.onSlideChanged = function(index){ $scope.currentIndex = index; for(var i in $scope.answerData){ $scope.answerArray.push($scope.answerData[i]); } console.log('index22:' + index); $scope.selectedIndex = parseInt($scope.answerData[$ionicSlideBoxDelegate.currentIndex()+1])-1 ; console.log('selectedIndex : ' +$scope.selectedIndex) for(var i in $scope.answerData){ if(i == ($ionicSlideBoxDelegate.currentIndex()+1)){ $scope.newJsonData.push($scope.singleData[i-1].items[($scope.answerData[i])]); $scope.selectedIndex = $scope.answerData[i] - '0' ; } console.log('index:' + $scope.selectedIndex) } // if($ionicSlideBoxDelegate.currentIndex()+1 > $scope.serveLength){ // osingMes.style.display = 'none'; // omulit.style.display = 'block'; // } console.log('jsonNewData:' + JSON.stringify( $scope.newJsonData)); //如果為多選的話,為$scope.multiData // $scope.answerMutleData = data.multi; console.log( JSON.stringify($scope.answerMutleData)); //對數組進行解析 var temp = 0; for(var i in $scope.answerMutleData){ //i為3 // var b = $scope.newMulitJsonData; //將上一次的值賦給b console.log('length :' + $scope.newMulitJsonData.length); var arr = $scope.answerMutleData[i].split('/'); for(var j=0;j < arr.length; j++){ console.log('test: ' + temp ); if(i == ($ionicSlideBoxDelegate.currentIndex()+1)){ if($scope.newMulitJsonData[j] == null){ //判斷之前的所有選項是否為空 $scope.newMulitJsonData.push($scope.multiData[temp].items[(arr[j])]); $scope.muiteKey = $scope.multiData[temp] - '0'; }else{ $scope.newMulitJsonData = []; $scope.newMulitJsonData.push($scope.multiData[temp].items[(arr[j])]); } } console.log('json: '+ JSON.stringify($scope.newMulitJsonData)); } temp++; //[1,2,3] } console.log(JSON.stringify($scope.newMulitJsonData)); for(var i in $scope.newMulitJsonData){ console.log('i:'+ i); } //console.log($scope.newMulitJsonData); //得到的正確答案沒問題 //所有的單選全部展示完成後,開始展示所有的多選 $scope.selectedMulitIndex = parseInt($scope.answerMutleData[$ionicSlideBoxDelegate.currentIndex()+1]) ; console.log( $scope.selectedMulitIndex); }; $scope.nextSlide = function(){ if($ionicSlideBoxDelegate.currentIndex()+1 != $scope.serveLength) { $ionicSlideBoxDelegate.next(); }else { var alertPopup = $ionicPopup.alert({ template: '親,已經最後一題,木有了哦!' }); alertPopup.then(function(res) { // window.location.reload(); // history.go(-1); }); } }; $scope.startSlide = function(){ $ionicSlideBoxDelegate.previous(); }; }])
5.前後端跨域的問題。
由於angularjs的$http請求與ajax還是有些區別的,總是會存在跨域的問題,如何解決呢?加個 withCredentials :true 即可。
$http({ url : "http://10.32.33.4:8080/ivotel-examuser/questionnairePapers/Submit", method : "post", data : submitTotalData, headers: { 'Content-Type': 'application/json;charset=UTF-8' }, withCredentials :true }).success(function(data) { console.log('success'); }).error(function(){ console.log('error'); });
})
OK,基本上整個核心的功能點都已經講解清楚啦。問題還是遇到不少,感謝從不拒絕我問題的shu,給了我很大的幫助。嘿嘿,麽麽噠!
三:總結
經過這個月的項目實踐,熟悉了不少ng的寫法,雖然以前也接觸過,但好像都不是很熟,而且一個完整的APP的搭建流程也熟悉很多。其次,想說到前後端合作的問題,定契約的問題,溝通問題
感覺一個項目下來,反正各種問題都碰到,大家一起吵啊,爭啊,各有各的想法,拍桌子啊,前後端互相抱怨啊,雖然意見各有不同,哈哈哈,還是很高興的!起碼團隊很有活力,很有想法,要都是
不吭聲,那才恐怖,自己搞自己的,誰知道你什麼想法。哈哈哈,喜歡我們的團隊,一個個都棒棒的!另外呢,做項目的時候呢,要知道每個人都有自己的想法,所以,不要一昧的否認別人的想法,覺
得自己就是對的(傻逼), 學會傾聽,很關鍵。團隊獲得了第一名,大家都很開心,當晚我們組大家一起去吃了海鮮自助。哈哈,放張照片!
還是喜歡和自己年齡相仿的人一起工作,做項目,開開玩笑,多開心。每天充滿了激情和活力,溝通無代溝,都是90後,一群年輕人,多好!可是,事與願違啊!接下來,還是得適應不同年齡段的人!
作者:婷風
出處:http://www.cnblogs.com/jtjds/p/6128539.html
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”將是我最大的寫作動力!歡迎各位轉載,但是未經作者本人同意
轉載文章之後必須在 文章頁面明顯位置給出作者和原文連接否則保留追究法律責任的權利。