1. 程式人生 > >實現雙擊進入編輯,失去焦點後儲存資料(Angular)

實現雙擊進入編輯,失去焦點後儲存資料(Angular)

      最近做一個專案,前端由Angular搭建,需要實現一個功能,就是雙擊進入編輯,當失去焦點的時候把資料儲存。(即改變雙向繫結的資料)。

        先寫一些簡陋的HTML程式碼:
    <table class="table1">
	   <tr>
	       <td></td>
               <td></td>
               <td></td>
	   </tr>
    </table>

      測試的資料如下:

	 $scope.data = [{id:1,name:'huang',age:22},{id:2,name:'zhao',age:22},
                       {id:3,name:'zhou',age:20},{id:4,name:'sun',age:22}];
      把資料顯示在檢視上:
    <table class="table1">
	   <tr ng-repeat="item in data">
	      <td>{{item.id}}</td>
	      <td ng-dblclick="replace($event,item,'name')"><span>{{item.name}}</span></td>
	      <td ng-dblclick="replace($event,item,'age')"><span>{{item.age}}</span></td>
	   </tr>
	</table>
      為了看起來舒服一些,隨便寫點樣式:
   table td{
          width:200px;
	  border:1px solid #ccc;
	  text-align:center;
   }
   table td span{           //這個樣式很重要,讓span充滿整個td,防止點選時,獲取到的物件是td而不是span
          display:block;
	  width:100%;
	  height:100%;
   }
   table{
          border-collapse:collapse;
   }
     顯示的結果如下:

  

JS程式碼
 angular.module('test',[]).controller('testController',function($scope){
    
	 $scope.data = [{id:1,name:'huang',age:22},{id:2,name:'zhao',age:22},{id:3,name:'zhou',age:20},{id:4,name:'sun',age:22}];
	 
	 $scope.replace = function($event,dataObj,name){
		/*
		*  $event是事件,dataObj是$scope.data中一個數據物件,
		*   name是是資料物件的具體屬性名 
		*/
		
	    var obj = $event.target;	//獲取被雙擊的物件
						
		//轉換成由span轉換為輸入框
	    var input = document.createElement("input");
		input.value = obj.innerHTML;
		obj.parentNode.replaceChild(input,obj);
		
		//失去焦點時由input輸入框轉換為span
		input.onblur = function(){
		   obj.innerHTML = input.value;
		   
		   //改變雙向繫結的資料,如果雙向繫結的資料是是Number型別,
		   //則把input輸入的值轉換為Number值,這個可以根據實際需要進行轉換
		   dataObj[name] = angular.isNumber(dataObj[name])?parseInt(input.value):input.value;
		   
		   input.parentNode.replaceChild(obj,input);
		   
		   //在console裡列印結果,檢視雙向繫結的資料是否改變
		   console.table($scope.data);
		};
		
	 };
   });

實驗結果:

但是做了一些測試後,發現了幾個小問題,

問題1:當單擊出現文字框後(此時只是出現文字框,但是焦點沒在文字框上),再去點選其他資料,又出現文字框,之前那個文字框並沒有轉換為span。看下圖:


解決方法,當span被input代替的時候,聚焦到input,input.focus();

問題2:當點選td時,轉換為input後,點選同一個td的非input區域。


問題3:不停點選已經出現的input,會報錯。出現下圖現象。


問題2、問題3解決,判斷是否是span節點,然後再賦予點選事件。obj.nodeName=='SPAN'
  

一個簡單的雙擊進入編輯算是完成了。或許還有其他的bug,以後發現了,再做修改。

完整的程式碼如下所示:

<!DOCTYPE>
<html ng-app="test">
<head>
<script src="http://lib.sinaapp.com/js/angular.js/angular-1.2.19/angular.min.js"></script>
<script>
   angular.module('test',[]).controller('testController',function($scope){
    
	 $scope.data = [{id:1,name:'huang',age:22},{id:2,name:'zhao',age:22},{id:3,name:'zhou',age:20},{id:4,name:'sun',age:22}];
	 
	 $scope.replace = function($event,dataObj,name){
		
	 var obj = $event.target;			
	
        //當被雙擊的是span元素時,才執行事件		
		if(obj.nodeName=='SPAN'){
				
			//轉換成輸入框
			var input = document.createElement("input");
			input.value = obj.innerHTML;
			obj.parentNode.replaceChild(input,obj);
			//聚焦的替換後的input上
			input.focus();
			
			input.onblur = function(){
			   obj.innerHTML = input.value;
			   dataObj[name] = angular.isNumber(dataObj[name])?parseInt(input.value):input.value;
			   input.parentNode.replaceChild(obj,input);
			   console.table($scope.data);
			};		
		}									
	 };
   });
</script>
<style>
   table td{
           width:200px;
	  border:1px solid #ccc;
	  text-align:center;
   }
   table td span{
          display:block;
	  width:100%;
	  height:100%;
   }
   table{
      border-collapse:collapse;
   }
</style>
</head>
<body ng-controller="testController">
    <table class="table1">
	   <tr ng-repeat="item in data">
	      <td>{{item.id}}</td>
	      <td ng-dblclick="replace($event,item,'name')"><span>{{item.name}}</span></td>
	      <td ng-dblclick="replace($event,item,'age')"><span>{{item.age}}</span></td>
	   </tr>
    </table>
</body>
</html>


僅作為筆記記錄。