Home > Back-end >  Set the HTML <input> step Attribute in Entity Framework
Set the HTML <input> step Attribute in Entity Framework

Time:11-24

Is there a way using annotations to define the "step" attribute? Currently I can only set it by directly setting this in the views

<input asp-for="Quantity" class="form-control" ste="1" />

My model just defines a range currently, which doesn't work with the min/max html attributes:

[Range(0, 9999999)]
public int Quantity { get; set; }

CodePudding user response:

With the hint from a comment, I was able to find and figure this out.

These are the snippets from the code. First an attribute for Step

    public class StepAttribute : ValidationAttribute
    {
        public StepAttribute(double increment)
        {
            Increment = increment;
        }

        public StepAttribute(int increment)
        {
            Increment = increment;
        }

        public double Increment { get; private set; }

        public override bool IsValid(object value)
        {
            if (int.TryParse(value.ToString(), out int i))
                return i > 0;
            else if (double.TryParse(value.ToString(), out double d))
                return d > 0;
            return false;
        }
    }

Then a tag helper

    [HtmlTargetElement("input", Attributes = "asp-for")]
    public class InputStepTagHelper : TagHelper
    {
        public override int Order { get; } = int.MaxValue;

        [HtmlAttributeName("asp-for")]
        public ModelExpression For { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            base.Process(context, output);

            if (context.AllAttributes["step"] == null)
            {
                var increment = GetStepIncrement(For.ModelExplorer.Metadata.ValidatorMetadata);
                if (increment > 0)
                    output.Attributes.Add("step", increment);
            }
        }

        private static double GetStepIncrement(IReadOnlyList<object> validatorMetadata)
        {
            if (validatorMetadata.Count == 0)
                return 0;

            for (var i = 0; i < validatorMetadata.Count; i  )
                if (validatorMetadata[i] is StepAttribute myAttribute && myAttribute.Increment > 0)
                    return myAttribute.Increment;
            return 0;
        }
    }

I had to add @addTagHelper *, ProjectName to my _ViewImports

Using the same logic, I added one for the Range to act as a Min/Max to the tag helper

    [HtmlTargetElement("input", Attributes = "asp-for")]
    public class InputMinMaxTagHelper : TagHelper
    {
        public override int Order { get; } = int.MaxValue;

        [HtmlAttributeName("asp-for")]
        public ModelExpression For { get; set; }

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            base.Process(context, output);

            if (context.AllAttributes["min"] == null)
            {
                // Attempt to check for a MaxLength annotation
                var min = GetMinvalue(For.ModelExplorer.Metadata.ValidatorMetadata);
                if (min.HasValue)
                    output.Attributes.Add("min", min.Value);
            }

            if (context.AllAttributes["min"] == null)
            {
                var max = GetMaxvalue(For.ModelExplorer.Metadata.ValidatorMetadata);
                if (max.HasValue)
                    output.Attributes.Add("max", max.Value);
            }
        }

        private static double? GetMinvalue(IReadOnlyList<object> validatorMetadata)
        {
            if (validatorMetadata.Count == 0)
                return null;

            for (var i = 0; i < validatorMetadata.Count; i  )
                if (validatorMetadata[i] is RangeAttribute myAttribute && double.TryParse(myAttribute.Minimum.ToString(), out double d))
                    return d;

            return null;
        }
        private static double? GetMaxvalue(IReadOnlyList<object> validatorMetadata)
        {
            if (validatorMetadata.Count == 0)
                return null;

            for (var i = 0; i < validatorMetadata.Count; i  )
                if (validatorMetadata[i] is RangeAttribute myAttribute && double.TryParse(myAttribute.Maximum.ToString(), out double d))
                    return d;

            return null;
        }

CodePudding user response:

Use the HtmlHelpers and see. Helper methods make it easy to bind to view data or model data especially with anotattions you are using

  • Related