• angularjs和ajax的结合使用 (二)


    今天我们来继续丰富上次的例子。我们来搞些 稍微复杂点的应用。

    首先我们来加一个全选 的功能。

    上一篇的例子里我们看到 分页时载入的是我们通过linq 查询自定义列 然后构建的匿名类 。使用这种EF框架+linq 查询的方式 我认为不方便的一点就是 要不你就只能select 一个固定对应表的数据模型类名 ,但是序列化成json的时候对外键类引用有天然的bug  ,就是框架自动序列化成json格式时会出循环引用错误 。序列化类型为XX的对象时检测到循环引用。没办法 我们能做的就是屏蔽某些属性 。方式就是在字段属性上方加上[AjaxPro.AjaxNonSerializable] 光这样还不行 如果 字段属性 有 virtual 关键字 还会报错,但是EF写数据模型代码的时候 外键属性如果不加virtual 修饰 就等于废的 外键抓不过来的。真是令人蛋疼的问题。大多数情况我们查询都不会只查询单一表的数据 并且基本还是用匿名类的方式 想用什么字段用什么字段 外键也可以及时查询出来 。综合上面的问题 还是用匿名类的方式 。

     如果你希望客户端传回来的数据对象 自动序列化成你的C#数据模型类 。也有些需要注意的地方 除了上面我说的 ,还有:
    1不能用Ilist 直接使用List 数组没试过 好像也不行 。

    2为了你传到客户端的json数据 又能够无缝的传回来。 在使用匿名类linq方式查询的时候 如果你想从客户端自动序列化成你C#数据模型类的属性 那么你就把匿名查询时的字段名称写成一样。

    3字段并不一定要一一完整对应  框架会检查你服务端接收参数的数据模型类有哪些字段 然后从返回的json数据里找 不符合的字段 他不会管的 并且也不会报错 只找json数据里符合的字段 然后序列化成 你c#数据模型类  这点我认为框架处理的非常好 非常智能。比如上面全选 的功能 我就给表格上绑的数据多加了一列 列名为chk 类型为bool 为true 则选中  没有这个字段 或者为false 都为没选中,

    4并且javascript这个很烂的东西 有个好处就是 变量可以灵活的使用 无类型限制。比如可以随意定义json格式的数据var person={name:"xiang"}  定义完过后 可以继续在其基础上添加内容 像这样 person.chk=true 。

    我们做这个功能正是利用了上述原理。

    表格头部加个 全选功能的复选框

    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 }

    运行效果:

    源码文件还是基于上一篇更改,直接下载上一篇的源码即可。

  • 相关阅读:
    常用AIX论坛地址介绍
    向日葵任务甘特图 http://www.51diaodu.cn/
    centos 中tomcat加入自启动​【转】
    徐州出差几天
    Unit OneC
    周末来了~
    北京展览馆参加第6届石油石化装备展览会
    王心凌 我会好好的 cyndi with u
    VS中Debug与Release、_WIN32与_WIN64的区别
    c语言中<stdbool.h>的使用
  • 原文地址:https://www.cnblogs.com/assassinx/p/4920016.html
Copyright © 2020-2023  润新知