angularjs + seajs構建Web Form前端(三) -- 相容easyui

來源:互聯網
上載者:User

在上一章中使用了angular實現了ajax form和樹形結構,經過以上兩章對於angular的大致使用,對於angular也有了初步的認識,接下來的內容只會對angular的一些用法做簡單的說明,如果有不清楚的可以自己查看angular API或者留言給我。   剛開始接觸angular的時候,我以為會拋棄諸如jQueryUI、easyui這樣的ui組件,但是隨著我學習後才發現,其實是我被自己的想法給誤導、局限了。mvvm通過資料與ui的綁定,實現雙向的同步,使用其他ui的組件我們一樣可以通過資料的變化來實現ui組件的狀態變化,通過ui組件的一些變化來變更繫結資料也是行的通的。 問題   1、input類型控制項   2、清單類型控制項   3、C#擴充 input類型控制項   由於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> //jsangular.module('test', []).controller('MainController', function ($scope) {    var age = $('[numberboxname=age]');     $scope.editData = {};     $scope.save = function () {        console.log($scope.editData);        $scope.editData = {};    };});  當點擊儲存的時候,發現代碼是運行正常的,可以在控制台內看到名字和年齡的值,但是這裡有一個BUG,那就是當儲存資料以後,要再次輸入年齡的時候,年齡還是顯示上次輸入的值,因此需要在重設editData的時候將numberbox的值設定為預設值,代碼就不寫了。 清單類型控制項   像numberbox、validatebox、datebox等input類型控制項,都可以通過ngModel加上一些代碼來實現資料的雙向繫結,相對來說還是很簡單的,但是像combo、combobox、combotree等就沒辦法直接使用ngModel進行綁定了,因為這些控制項會產生額外的html代碼,這是NG無法控制到的,因為這些控制項的一些自身的事件機制並不能在ng內發揮作用,相反還會影響ng的正常運行,因此只能根據自身的業務來對它們進行一些擴充,這裡以combobox為例子,實現思路大致如下:   1、自訂指令產生下拉單html   2、手動初始化combobox並將綁定欄位的值設定到combobox上   3、當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) //ViewModelpublic class Person{    [NgModel("editData.name")]    public string Name { get; set; }}  產生的結果跟原來的是一樣的,這樣就完成了對NG的擴充了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.