回顾css
在上一章中使用了angular实现了ajax form和树形结构,通过以上两章对于angular的大体使用,对于angular也有了初步的认识,接下来的内容只会对angular的一些用法作简单的说明,若是有不清楚的能够本身查看angular API或者留言给我。
html
刚开始接触angular的时候,我觉得会抛弃诸如jQueryUI、easyui这样的ui组件,可是随着我学习后才发现,实际上是我被本身的想法给误导、局限了。mvvm经过数据与ui的绑定,实现双向的同步,使用其余ui的组件咱们同样能够经过数据的变化来实现ui组件的状态变化,经过ui组件的一些变化来变动绑定的数据也是行的通的。ajax
问题bootstrap
一、input类型控件app
二、列表类型控件mvvm
三、C#扩展学习
input类型控件ui
因为easyui大部分的控件均可以基于input,如validatebox、datebox、numberbox等,试着使用ngModel直接在这些控件上进行绑定,代码以下:编码
//html <div id="main" ng-controller="MainController"> 名字:<input type="text" ng-model="editData.name" /> <br /> 年龄:<input name="age" class="easyui-numberbox" ng-model="editData.age" /> <br /> <a href="#" class="easyui-linkbutton" ng-click="save()">保存</a> </div> //js angular.module('test', []).controller('MainController', function ($scope) { var age = $('[numberboxname=age]'); $scope.editData = {}; $scope.save = function () { console.log($scope.editData); $scope.editData = {}; }; });
当点击保存的时候,发现代码是运行正常的,能够在控制台内看到名字和年龄的值,可是这里有一个BUG,那就是当保存数据之后,要再次输入年龄的时候,年龄仍是显示上次输入的值,所以须要在重置editData的时候将numberbox的值设置为默认值,代码就不写了。spa
列表类型控件
像numberbox、validatebox、datebox等input类型控件,均可以经过ngModel加上一些代码来实现数据的双向绑定,相对来讲仍是很简单的,可是像combo、combobox、combotree等就没办法直接使用ngModel进行绑定了,由于这些控件会生成额外的html代码,这是NG没法控制到的,由于这些控件的一些自身的事件机制并不能在ng内发挥做用,相反还会影响ng的正常运行,所以只能根据自身的业务来对它们进行一些扩展,这里以combobox为例子,实现思路大体以下:
一、自定义指令生成下拉单html
二、手动初始化combobox并将绑定字段的值设置到combobox上
三、当combobox选择值的时候将值更新到绑定的字段上
根据以上思路,实现代码以下:
//其余的省略 .directive('esCombobox', function () { return { replace: true, restrict: 'E', template: '<select></select>', scope: { data: '=', value: '@' }, link: function (scope, element, attrs) { var props = scope.value.split('.'); var current = getBinder(); element.combobox({ data: scope.data, onSelect: function (r) { var binder = getBinder(); binder.obj[binder.field] = r.value; } }).combobox('setValue', current.obj[current.field]); function getBinder() { return props.length == 1 ? { obj: scope.$parent, field: props[0] } : { obj: scope.$parent[props[0]], field: props[1] }; }; } }; });
以上方法之因此要将getBinder独立出来,是由于每次操做的绑定对象都是不一样的(editData在保存以后会被从新赋值,引用的对象不一样了)。
C#扩展
有时候当咱们使用服务端脚原本生成html的时候,咱们可能会使用以下代码来进行绑定:
<input type="text" ng-model="editData.name" ng-init="editData.name='<%=Model.Name %>'"/>
以上html代码能够发现,editData.name是绑定的字段,而ngInit内初始化赋值能够直接从Model中获取,咱们能够建立一个NgModelAttribute的特性,而后该特性内提供一个属性用来存储绑定的字段,大体代码以下:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class NgModelAttribute : Attribute, ITagBuilderWrapper { private string m_BindName; public string BindName { get { return m_BindName; } } public NgModelAttribute(string bindName) { m_BindName = bindName; } }
而后使用服务端脚本生成Html的时候,获取表达式指定的属性包含的NgModelAttribute特性以及Model的值来生成以上的html,大体代码以下:
public static string Control(string tag, Expression<Func<TModel, object>> exp, TModel model) { var builder = new TagBuilder(tag); string propertyName = PropertyHelper.ResolveName(exp); var property = model.GetType().GetProperty(propertyName); var attrs = property.GetCustomAttributes(typeof(NgModelAttribute), false); if (attrs.Length > 0) { var ngModel = attrs[0] as NgModelAttribute; builder.AddAttribute("ng-model", ngModel.BindName); if (model != null) { var propertyValue = property.GetValue(model, null); string initValue; if (property.PropertyType == typeof(string) || property.PropertyType == typeof(Guid)) { initValue = string.Format("'{0}'", propertyValue.ToString()); } else if (property.PropertyType == typeof(DateTime)) { try { var date = Convert.ToDateTime(propertyValue); initValue = string.Format( "new Date(1970, 0, 1, 0, 0, {0})", Convert.ToInt32((date - new DateTime(1970, 1, 1)).TotalSeconds)); } catch { initValue = "new Date()"; } } else { initValue = propertyValue.ToString(); } builder.AddAttribute("ng-init", string.Format("{0}={1}", ngModel.BindName, initValue)); } } return builder.ToString(); }
以上代码仅做为参考,其中大部分的代码主要是用于判断绑定ngInit的值,由于不一样值绑定的方式不一样。那么接下来只要将最初的代码改成以下:
//html <%=HtmlHelper.Control<Person>("input", p => p.Name, Person) //ViewModel public class Person { [NgModel("editData.name")] public string Name { get; set; } }
生成的结果跟原来的是同样的,这样就完成了对NG的扩展了。
结尾
因为这次是在学习angular的过程中,遇到了控件组的问题,因为本人对于css实在是很烂,没法实现漂亮的组件因而我就放弃了,便有了想要继续使用easyui的念头,可是引入easyui后发现它与bootstrap存在着样式兼容性问题,所以移除了bootstrap,可是编码当中发现了2个库之间的各类原理上的冲突,通过几回失败以后,终于找到了能够将2者结合在一块儿的方法,所以就有了此篇文章,但愿这次分享能给其余人带来帮助,若是存在问题或者错误的话,请告诉我,谢谢。