angularjs和ajax的結合使用 (二)

今天咱們來繼續豐富上次的例子。咱們來搞些 稍微複雜點的應用。javascript

首先咱們來加一個全選 的功能。html

上一篇的例子裏咱們看到 分頁時載入的是咱們經過linq 查詢自定義列 而後構建的匿名類 。使用這種EF框架+linq 查詢的方式 我認爲不方便的一點就是 要不你就只能select 一個固定對應表的數據模型類名 ,可是序列化成json的時候對外鍵類引用有自然的bug  ,就是框架自動序列化成json格式時會出循環引用錯誤 。序列化類型爲XX的對象時檢測到循環引用。沒辦法 咱們能作的就是屏蔽某些屬性 。方式就是在字段屬性上方加上[AjaxPro.AjaxNonSerializable] 光這樣還不行 若是 字段屬性 有 virtual 關鍵字 還會報錯,可是EF寫數據模型代碼的時候 外鍵屬性若是不加virtual 修飾 就等於廢的 外鍵抓不過來的。真是使人蛋疼的問題。大多數狀況咱們查詢都不會只查詢單一表的數據 而且基本仍是用匿名類的方式 想用什麼字段用什麼字段 外鍵也能夠及時查詢出來 。綜合上面的問題 仍是用匿名類的方式 。前端

 若是你但願客戶端傳回來的數據對象 自動序列化成你的C#數據模型類 。也有些須要注意的地方 除了上面我說的 ,還有:
1不能用Ilist 直接使用List 數組沒試過 好像也不行 。java

2爲了你傳到客戶端的json數據 又可以無縫的傳回來。 在使用匿名類linq方式查詢的時候 若是你想從客戶端自動序列化成你C#數據模型類的屬性 那麼你就把匿名查詢時的字段名稱寫成同樣。jquery

3字段並不必定要一一完整對應  框架會檢查你服務端接收參數的數據模型類有哪些字段 而後從返回的json數據裏找 不符合的字段 他不會管的 而且也不會報錯 只找json數據裏符合的字段 而後序列化成 你c#數據模型類  這點我認爲框架處理的很是好 很是智能。好比上面全選 的功能 我就給表格上綁的數據多加了一列 列名爲chk 類型爲bool 爲true 則選中  沒有這個字段 或者爲false 都爲沒選中,angularjs

4而且javascript這個很爛的東西 有個好處就是 變量能夠靈活的使用 無類型限制。好比能夠隨意定義json格式的數據var person={name:"xiang"}  定義完事後 能夠繼續在其基礎上添加內容 像這樣 person.chk=true 。數據庫

咱們作這個功能正是利用了上述原理。json

表格頭部加個 全選功能的複選框c#

1 <th>
2                                 <input id="Checkbox1" ng-click="selectAll($event)" type="checkbox" />全選
3                                 
4                             </th>

都知道在javascript裏面 調用函數時 要把當前單擊的控件對象傳進去 使用this ,angularjs 裏面不同 使用$event 。那麼對應的功能函數又是怎樣的呢後端

 1 //全選
 2 $scope.selectAll = function (sender) {
 3     if ($(sender.target).is(':checked')) {
 4         for (var i = 0; i < $scope.data.length; i++) {
 5             $scope.data[i].chk = true;
 6         }
 7     }
 8     else {
 9         for (var i = 0; i < $scope.data.length; i++) {
10             $scope.data[i].chk = false;
11         }
12     }
13 }

而後再行循環裏面 弄個複選框的雙向綁定就能夠了

1 <td>
2     <input ng-checked="{{stu.chk}}" ng-model="stu.chk" type="checkbox" /></td>

看 就能夠了 雖然咱們回傳的數據多了個chk屬性 可是依然可以被成功解析成StudentsInfo對象。angularjs裏面很是看重數據操做跟界面上的對應關係  讓你的程序更加面向對象化。

接下來咱們來講下一些經常使用的數據格式化方式。angularjs裏面自帶了一些自帶的filter 可提供格式化日期 這些 {{ stu.createDate | date: 'yyyy年MM月dd' }}

找了下沒找到格式化布爾值的方式。還本身寫了個filter:

 1 app.filter('odditems', function () {
 2     return function (inputArray) {
 3         if (inputArray == true)
 4             return '';
 5         else if (inputArray == false)
 6             return '';
 7         else
 8             return '';
 9     }
10 });

後來證實徹底是我多慮了 ,原來angularjs的表達式 也支持三元運算 :{{stu.isChecked==true?'yes':''}}
接下來繼續擴展上面的例子 來加個複選項的功能

最多見的那種就是愛好  你有神馬愛好 打籃球 羽毛球 游泳 ,哇哈哈 , 別打我。這是一個多對多的關係 可能會想到專門建一個表來存儲這些東西 ,用不着啦 。直接加個文本字段 以逗號隔開就能夠了。

先展現一個網上的一個複選功能的例子:

 1 <body ng-app="app">
 2     <div ng-controller="MainCtrl" class="container bg-color">
 3         <section>
 4             <pre>{{choseArr}}</pre>
 5             全選: <input type="checkbox" ng-model="master" ng-click="all(master,tesarry)">
 6             <div ng-repeat="z in tesarry">
 7                 <input id={{z}} type="checkbox" ng-model="x" ng-checked="master" ng-click="chk(z,x)">{{z}}
 8             </div>
 9             <a href="#" class="btn btn-danger" ng-click="delete()"> 刪除</a>
10         </section>
11     </div>
12     <script>
13         var app = angular.module('app', []);
14         app.controller('MainCtrl', function ($scope, $http, $timeout) {
15             $scope.tesarry = ['1', '2', '3', '4', '5'];//初始化數據
16             $scope.choseArr = [];//定義數組用於存放前端顯示
17             var str = "";//
18             var len = $scope.tesarry.length;//初始化數據長度
19             var flag = '';//是否點擊了全選,是爲a
20             $scope.x = false;//默認未選中
21 
22             $scope.all = function (c, v) {//全選
23                 if (c == true) {
24                     $scope.x = true;
25                     $scope.choseArr = angular.copy(v);
26                     flag = 'a';
27                 } else {
28                     $scope.x = false;
29                     $scope.choseArr = [];
30                     flag = 'b';
31                 }
32             };
33             $scope.chk = function (z, x) {//單選或者多選
34                 if (flag == 'a') {//在全選的基礎上操做
35                     str = $scope.choseArr.join(',') + ',';
36                 }
37                 if (x == true) {//選中
38                     str = str + z + ',';
39                     flag = 'c'
40                     if ($scope.choseArr.length == len - 1) {
41                         $scope.master = true
42                     }
43                 } else {
44                     str = str.replace(z + ',', '');//取消選中
45                 }
46 
47                 $scope.choseArr = (str.substr(0, str.length - 1)).split(',');
48                 var dex = $scope.choseArr.indexOf("");//判斷數組中有沒有"",有的話返回值大於等於0,沒有返回-1
49                 if (dex >= 0) {
50                     $scope.choseArr.splice(dex, 1);//刪除數組中的"";
51                 };
52                 if ($scope.choseArr.length == 0) { $scope.master = false };
53             };
54             $scope.delete = function () {// 操做CURD
55                 if ($scope.choseArr[0] == "" || $scope.choseArr.length == 0) {//沒有選擇一個的時候提示
56                     alert("請至少選中一條數據在操做!")
57                     return;
58                 };
59                 for (var i = 0; i < $scope.choseArr.length; i++) {
60                     alert($scope.choseArr[i]);
61                     console.log($scope.choseArr[i]);//遍歷選中的id
62                 }
63             };//delete end
64         });
65     </script>
66 
67 </body>
View Code

我也不想多說 ,又叫變量又加這樣那樣處理的 。麻煩 複雜。我還不如直接用jquery呢。angularjs一直的理念就是 只關注數據模型。
其實你須要的是這樣一種格式的東西:

$scope.ar = [{ id: 1, name: "basketball", st: true }, { id: 2, name: "tennis", st: false }, { id: 3, name: "swimming", st: true }];

st表明選中與否 id表明複選項的value值 name表明複選項的text值 而後用repeat一循環 是否是這樣  是否是應該這樣:

 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 5     <title>多選</title>
 6     <script type="text/javascript" src="../jquery-easyui-1.4.3/jquery.min.js"></script>
 7     <script type="text/javascript" src="../angularJs/angular.js"></script>
 8     <script>
 9         function myCtr($scope) {
10             //實現多選 看了網上的一個 又是弄中間變量 又是操做dom
11             //no 數據 組織方式  這纔是angular way   ,根本不須要那麼多操做 只須要操做數據 你只須要操做數據  看簡簡單單 清清爽爽
12             //按說的話這種需求是比較少的 若是設計功能的時候 你非要整這麼個 那麼沒辦法 數據結構就是這樣 你就得這麼作 別想偷懶
13             //你必須得造成這樣一種數據結構了 交給前端 
14             $scope.ar = [{ id: 1, name: "basketball", st: true }, { id: 2, name: "tennis", st: false }, { id: 3, name: "swimming", st: true }];
15             $scope.ar2 = [2, 3];
16             $scope.exist = function (id) {
17                 for (var i = 0; i < $scope.ar2.length ; i++) {
18                     if ($scope.ar2[i] == id)
19                         return true;
20                 }
21                 return false;
22             }
23             $scope.show = function () {
24                 var rst = "";
25                 for (var i = 0; i < $scope.ar.length ; i++) {
26                     if ($scope.ar[i].st == true)
27                         rst += $scope.ar[i].name + ',';
28                 }
29                 alert(rst);
30             }
31         }
32     </script>
33 </head>
34 <body ng-app ng-controller="myCtr">
35     <ul>
36         <li ng-repeat="z in ar">
37             <input id="chk{{z.id}}" ng-checked="{{z.st}}" ng-model="z.st" type="checkbox" />
38             <label for="chk{{z.id}}">{{z.name}}</label>
39         </li>
40     </ul>
41     <hr />
42     <ul >
43         <li ng-repeat="z in ar">
44             <input id="chkk{{z.id}}" ng-checked="exist(z.id)" ng-model="z.st" type="checkbox" />
45             <label for="chkk{{z.id}}">{{z.name}}</label>
46         </li>
47     </ul>
48 
49     <input id="Button1" type="button" ng-click="show()" value="show" />
50    
51 </body>
52 </html>
View Code

爲了獲得上述那種格式的數據 原本在服務端編寫這樣的代碼 以屬性的方式呈現:

 1 public List<CheckboxItem> favorsValue
 2 {
 3     get
 4     {
 5         if(_favorsValue!=null)
 6             return _favorsValue;
 7         else if (string.IsNullOrEmpty(favors)==false)
 8         {
 9             Dal d = new Dal();
10             List<CheckboxItem> flist = d.GetAllFavors();
11             string[] curlist = favors.Split(',');
12             for (int i = 0; i < flist.Count; i++)
13             {
14                 for (int j = 0; j < curlist.Length; j++)
15                 {
16                     if (flist[i].id == curlist[j])
17                     {
18                         flist[i].Checked = true;
19                         continue;
20                     }
21                 }
22             }
23             return flist;
24             //return favors.Split(',');
25         }
26         else
27         {
28             Dal d = new Dal();
29             List<CheckboxItem> flist = d.GetAllFavors();
30             return flist;
31         }
32     }
33     set {
34         _favorsValue = value;
35     }
36    
37 }


好比咱們有三種不一樣的愛好 那麼把從數據庫裏都出來 ,而後根據每條數據各自不一樣的以逗號隔開的字符 轉換成

$scope.ar = [{ id: 1, name: "basketball", st: true }, { id: 2, name: "tennis", st: false }, { id: 3, name: "swimming", st: true }];

這樣的數據  。而後前端獲得的自動就是這種格式的數據了 操做後又跟後端作到無縫銜接。想法是好的總會遇到各類問題 這種屬性邏輯代碼必須寫在對應的數據模型代碼裏 給linq查詢帶來了限制。 若是使用匿名類的方式作linq查詢又調用不了這個邏輯 匿名類是調用不了邏輯代碼的 只可以作簡單的初始化屬性的工做 。爲了在匿名類裏調用方法我都找瘋了 結果仍是沒找到,最後仍是妥協了 把這個工做放到客戶端去處理。

 1 //多選框綁定
 2             $scope.transFav = function () {
 3                 if ($scope.curobj.favorsValue != null && $scope.curobj.favorsValue != undefined)
 4                     return;
 5                 if ($scope.curobj.favors) {
 6 
 7                     var d = [{ id: "1", name: "basketball", Checked: false }, { id: "2", name: "tennis", Checked: false }, { id: "3", name: "swimming", Checked: false }];
 8                     var curlist = $scope.curobj.favors.split(",");
 9                     for (var i = 0; i < d.length; i++) {
10                         for (var j = 0; j < curlist.length; j++) {
11                             if (d[i].id == curlist[j]) {
12                                 d[i].Checked = true;
13                                 continue;
14                             }
15                         }
16                     }
17                     $scope.curobj.favorsValue = d;
18                 }
19                 else {
20                     var d = [{ id: "1", name: "basketball", Checked: false }, { id: "2", name: "tennis", Checked: false }, { id: "3", name: "swimming", Checked: false }];
21                     $scope.curobj.favorsValue = d;
22                 }
23             }

可是在服務端屬性咱們仍是公開這麼一個屬性 public List<CheckboxItem> favorsValue{ get; set; } 讓客戶端更改數據後回傳能夠作到無縫銜接。客戶端數據綁定:

1 <ul>
2     <li ng-repeat="z in  curobj.favorsValue">
3         <input id="chkk{{z.id}}" ng-checked="z.Checked" value="{{z.id}}" name="favorchk" ng-model="z.Checked" type="checkbox" />
4         <label for="chkk{{z.id}}">{{z.name}}</label>
5     </li>
6 </ul>

客戶端改變favorsValue的內容服務端可獲知 而後從新組織成逗號隔開的字符串。固然這個工做你在客戶端作也是能夠的:

 1 //根據name 得到全部checkbox選取的的值
 2 function addMem(names) {
 3     var allNames = "";
 4     $("input[name='" + names + "']").each(function () {
 5         if ($(this).attr("checked") == "checked") {
 6             if (allNames == "") {
 7                 allNames = $(this).attr("value");
 8             } else {
 9                 allNames += "," + $(this).attr("value");
10             }
11         }
12     });
13     //alert(allNames);
14     return allNames;
15 }

運行效果:

源碼文件仍是基於上一篇更改,直接下載上一篇的源碼便可。

相關文章
相關標籤/搜索