3

Angular-Formly を使用して、一連の .NET クラスから動的にフォームを構築しようとしています。

クラスのプロパティ情報をjsonでシリアライズしてFormlyに返すのですが、フィールドが表示されません。

リモートで生成された json から angular- formly vm.fields オブジェクトをロードする方法は? しかし、私にはうまくいかないようです。

私のフォームコードは次のとおりです。

<form ng-submit="vm.onSubmit()" novalidate>
   <formly-form model="vm.model" fields="vm.formFields">
      <button type="submit" class="btn btn-primary submit-button">Submit</button>
   </formly-form>
</form>

角度コードは次のとおりです。

<script>
    /* global angular */
    (function () {
        'use strict';

        var app = angular.module('formlyExample', ['formly', 'formlyBootstrap'], function config(formlyConfigProvider) {
            // set templates here
            //formlyConfigProvider.setType({
            //    name: 'custom',
            //    templateUrl: 'custom.html'
            //});
        });

        app.factory('User', function ($http) {
            return {
                getFields: getFields
            };

            function getFields() {
                return $http.post('TestFormly.aspx/LoadData', { headers: { 'Cache-Control': 'no-cache' } });
            }
        });

        app.controller('MainCtrl', function MainCtrl($scope, $http, User) {
            var vm = this;
            // funcation assignment
            vm.onSubmit = onSubmit;

            vm.loadingData = User.getFields().then(function (result) {
                vm.fields = JSON.parse(result.data.d);
                vm.originalFields = angular.copy(vm.fields);
            });

            vm.model = {
            };

            // function definition
            function onSubmit() {
                alert(JSON.stringify(vm.model), null, 2);
            }
        });
    })();
</script>

CSharp.Net コードは次のとおりです。

    [WebMethod]
    public static string LoadData()
    {
        string retValue = null;

        List<FieldItem> m_fields = new List<FieldItem>();

        FieldItem item1 = new FieldItem();
        item1.key = "text";
        item1.type = "input";
        item1.templateOptions = new TemplateOptions() { label = "Text", placeholder = "Formly is terrific!" };

        FieldItem item2 = new FieldItem();
        item2.key = "story";
        item2.type = "textarea";
        item2.templateOptions = new TemplateOptions() { label = "Some sweet story", placeholder = "It allows you to build and maintain your forms with the ease of JavaScript :-)" };

        m_fields.Add(item1);
        m_fields.Add(item2);

        retValue = JsonConvert.SerializeObject(m_fields);

        return retValue;
    }

JSON の結果は次のとおりです。

[
    {
        "key":"text",
        "type":"input",
        "templateOptions":{
            "label":"Text",
            "placeholder":"Formly is terrific!"
        }
    },
    {
        "key":"story",
        "type":"textarea",
        "templateOptions":{
            "label":"Some sweet story",
            "placeholder":"It allows you to build and maintain your forms with the ease of JavaScript :-)"
        }
   }
]

firebug でデバッグすると、JSON が vm.fields に正しく渡されていることがわかりますが、入力ボックスは表示されず、Sumbit ボタンのみが表示されます。

Formly のにもフィールドが表示されていないことに気付きました。

手伝ってくれますか ?

よろしくお願いします、ジュゼッペ。

4

2 に答える 2

1

これは、私が自分自身の概念実証としてすぐにハッキングしたソリューションです。

基本的に、FormlyModelBuilder は ViewModel クラスをスキャンし、formly フィールド モデルを構築します。

使用例

public IActionResult Index()
        {
            return Ok(new ViewModels.Account.FormlyModelBuilder<ViewModels.Account.RegisterViewModel>().JsonStringify(new ViewModels.Account.RegisterViewModel { Email = "test@test.com" }));
        }

これを変換します

public class RegisterViewModel
{
    [Required]
    [EmailAddress]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare ("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

これに

{
  "fields": [{
    "key": "Email",
    "type": "email",
    "templateOptions": {
      "isRequired": false,
      "label": "Email"
    },
    "expressionProperties": {
      "templateOptions.focus": "Email"
    }
  }, {
    "key": "Password",
    "type": "password",
    "templateOptions": {
      "isRequired": false,
      "label": "Password"
    },
    "expressionProperties": {}
  }, {
    "key": "ConfirmPassword",
    "type": "password",
    "templateOptions": {
      "label": "Confirm password"
    },
    "expressionProperties": {}
  }],
  "model": {
    "email": "test@test.com"
  },
  "expressionProperties": {}
}

ソースコード

public class FormlyModelBuilder<T>
    {
        internal T GetAttributeFrom<T>(object instance, string propertyName) where T : Attribute
        {
            var property = instance.GetType().GetProperty(propertyName);
            return GetAttributeFrom<T>(property);
        }
        internal T GetAttributeFrom<T>(PropertyInfo property) where T : Attribute
        {
            var attrType = typeof(T);
            T t = (T)property.GetCustomAttributes(attrType, false).FirstOrDefault();
            if (t == null)
            {
                var metaAttr = (MetadataTypeAttribute[])property.ReflectedType.GetCustomAttributes(typeof(MetadataTypeAttribute), true);
                if (metaAttr.Length > 0)
                {
                    foreach (MetadataTypeAttribute attr in metaAttr)
                    {
                        var subType = attr.MetadataClassType;
                        var pi = subType.GetField(property.Name);
                        if (pi != null)
                        {
                            t = (T)pi.GetCustomAttributes(attrType, false).FirstOrDefault();
                            return t;
                        }


                    }
                }

            }
            else
            {
                return t;
            }
            return null;
        }

        internal FormlyModel<T> Build(T dataModel)
        {
            if (dataModel == null) throw new ArgumentNullException(nameof(dataModel));
            //
            var modelType = typeof(T);
            var model = new FormlyModel<T>(dataModel);
            foreach (var property in modelType.GetProperties(BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Public))
            {
                var type = GetAttributeFrom<DataTypeAttribute>(property);
                var field = new FormlyField(property.Name, GetInputTypeFromDataType(type?.DataType, property.PropertyType));
                model.AddField(field);
                //
                var display = GetAttributeFrom<DisplayAttribute>(property);
                field.TemplateOptions.Label = display?.Name;
                //
                var required = GetAttributeFrom<RequiredAttribute>(property);
                field.TemplateOptions.IsRequired = required?.AllowEmptyStrings;
                //

            }
            var focusField = model.Fields.First();
            focusField.ExpressionProperties["templateOptions.focus"] = focusField.Key;
            return model;
        }
        internal string JsonStringify(T dataModel)
        {
            if (dataModel == null) throw new ArgumentNullException(nameof(dataModel));
            //
            var dcr = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
            dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
            //
            return Newtonsoft.Json.JsonConvert.SerializeObject(Build(dataModel),
                new Newtonsoft.Json.JsonSerializerSettings
                {
                    NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
                    ContractResolver = dcr
                });
        }

        private string GetInputTypeFromDataType(DataType? dataType, Type propertyType)
        {
            if (dataType != null)
            {
                //
                switch (dataType)
                {
                    case DataType.Text:
                        return "input";
                    case DataType.Password:
                        return "password";
                    case DataType.EmailAddress:
                        return "email";
                    case DataType.Html:
                    case DataType.MultilineText:
                    case DataType.Custom:
                    case DataType.DateTime:
                    case DataType.Date:
                    case DataType.Time:
                    case DataType.Duration:
                    case DataType.PhoneNumber:
                    case DataType.Currency:
                    case DataType.Url:
                    case DataType.ImageUrl:
                    case DataType.CreditCard:
                    case DataType.PostalCode:
                    case DataType.Upload:
                    default:
                        break;
                }
            }
            switch (propertyType.Name)
            {
                case nameof(System.Boolean):
                    return "checkbox";
                default:
                    return "input";
            }
        }
    }
    internal class FormlyModel<T>
    {
        internal FormlyModel(T dataModel)
        {
            if (dataModel == null) throw new ArgumentNullException(nameof(dataModel));
            //
            this.Fields = new List<FormlyField>();
            this.Model = dataModel;
            this.ExpressionProperties = new Dictionary<string, string>();
        }

        internal IEnumerable<FormlyField> Fields { get; }
        internal T Model { get; }
        internal Dictionary<string, string> ExpressionProperties { get; }
        internal void AddField(FormlyField field)
        {
            if (field == null) new ArgumentNullException(nameof(field));
            //
            ((List<FormlyField>)this.Fields).Add(field);
        }
    }
    internal class FormlyField
    {
        internal FormlyField(string key, string type)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentNullException(nameof(key));
            if (string.IsNullOrWhiteSpace(type)) throw new ArgumentNullException(nameof(type));
            //
            TemplateOptions = new TemplateOptions();
            ExpressionProperties = new Dictionary<string, string>();
            Key = key;
            Type = type;
        }
        internal string Key { get; }
        internal string Type { get; }
        internal string HideExpression { get; set; }
        internal TemplateOptions TemplateOptions { get; }
        internal Dictionary<string, string> ExpressionProperties { get; }
    }
    internal class TemplateOptions
    {
        public bool? IsRequired { get; set; }
        public string Label { get; set; }
        public string Placeholder { get; set; }
    }
于 2016-01-09T23:38:50.137 に答える