Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Html 5 Placeholder and Required attribute support to editor templates #4

Closed
wants to merge 3 commits into from

Conversation

paultyng
Copy link

@paultyng paultyng commented Nov 7, 2011

Now the inputs will render with these attributes when they are specified in metadata:

<input class="text-box single-line" id="RegularString" name="RegularString" placeholder="Enter your string..." required="required" type="text" value="">

Note the additional attributes. placeholder pulls from the ModelMetadata.Watermark, required pulls from ModelMetadata.IsRequired

@paultyng
Copy link
Author

paultyng commented Nov 7, 2011

The duplication of the attribute code definitely violates DRY, but I wanted to make sure the EditorTemplates supported copy/paste deployment if people only wanted to use a couple of them and not the whole project.

@BoPetersen
Copy link

Looks good, but I don't think that the required attribute should have the value "required", I went with true, even though both work. In my patch I added the required and the maxlength attributes, and have the static attribute written a bit more concise.
Besides the other attributes that are not yet part of the templates, I can't figure out how to pass the HTML attributes specified with an annonymous object when calling the .EditorFor method, to the TextBox helper method.

@paultyng
Copy link
Author

paultyng commented Nov 8, 2011

From the spec:

A number of attributes are boolean attributes. The presence of a boolean attribute on an element represents the true value, and the absence of the attribute represents the false value.

If the attribute is present, its value must either be the empty string or a value that is an ASCII case-insensitive match for the attribute's canonical name, with no leading or trailing whitespace.

http://www.w3.org/TR/html5/common-microsyntaxes.html#boolean-attribute

You may want to dig in to the HTML 5 spec a bit more. For example placeholder and required are not actually valid on the date/time/month inputs and stuff like that, you can't just put that on every input.

In terms of the EditorFor the goal is that you wouldn't actually pass any HTML attributes to it, its meant as an abstraction to the view template where you don't know how it will be rendered. By allowing the passing of HTML attributes you would be coupling the editor implementation to the calling view implementation which isn't really how its intended to work.

@paultyng
Copy link
Author

paultyng commented Nov 8, 2011

I like the addition of maxlength, could also apply min/max/pattern attributes where applicable. We should look in to those as well.

@BoPetersen
Copy link

Again you are right. The value of required should be name, and placeholder and required should not be on some templates.

The purpose of passing HTML parameters was in the case of the "autofocus" attribute, which people using the templates should be able to specify themselves, how else would "autofocus" be set.

For the maxlength property I first tried it with the MaxLength annotation, but because MVC doesn't use it, this was not possible, and as StringLength can only be used for a max length, im not sure how to min length would be done, but min/max/pattern should be looked into.

@paultyng
Copy link
Author

paultyng commented Nov 8, 2011

Ah yeah in the autofocus case can probably add a ViewData lookup for that to work like the HTML attributes do in a TextBoxFor but it would be treated more as a model instead, but good idea to add functionality for that.

ReadOnly support could also be added as that property exists on the ModelMetadata.

@BoPetersen
Copy link

What I did in my project for autofocus is this:

if (ViewData["autofocus"] != null && ViewData["autofocus"].ToString().ToLower().Equals("autofocus")) { values.Add("autofocus", "autofocus"); }

But this only helps with the autofocus property, which is enough in my case, but not if other attributes are needed.
ReadOnly should definitely be added.

I was just looking into the DataAnnotationExtentions project, which might help with some of the attributes, and can be made a dependency in the NuGet package.

@BoPetersen
Copy link

We can just do readonly with:

if (ViewData.ModelMetadata.IsReadOnly) { values.Add("readonly", "readonly"); }

Just like with required.

@BoPetersen
Copy link

I have added min and max.

Sorry for putting everything together, min/max should of course not be specified for textbox.

@{ Dictionary<string, object> values = new Dictionary<string, object>() { { "class", "text-box single-line" }, { "type", "text" } };
values.Add("placeholder", ViewData.ModelMetadata.Watermark);
if (ViewData.ModelMetadata.IsRequired) { values.Add("required", "required"); }
if (ViewData.ModelMetadata.IsReadOnly) { values.Add("readonly", "readonly"); }
if (ViewData["autofocus"] != null && ViewData["autofocus"].ToString().ToLower().Equals("autofocus")) { values.Add("autofocus", "autofocus"); }
IEnumerable rules = ModelValidatorProviders.Providers.GetValidators(ViewData.ModelMetadata, ViewContext).SelectMany(x => x.GetClientValidationRules());
ModelClientValidationRule lengthRule = rules.FirstOrDefault(x => x.ValidationType.ToLower().Equals("length"));
if (lengthRule != null && lengthRule.ValidationParameters.ContainsKey("max")) { values.Add("maxlength", lengthRule.ValidationParameters["max"]); }
ModelClientValidationRule rangeRule = rules.FirstOrDefault(x => x.ValidationType.ToLower().Equals("range"));
if (rangeRule != null && rangeRule.ValidationParameters.ContainsKey("min")) { values.Add("min", rangeRule.ValidationParameters["min"]); }
if (rangeRule != null && rangeRule.ValidationParameters.ContainsKey("max")) { values.Add("max", rangeRule.ValidationParameters["max"]); }
}
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, values)

@BoPetersen
Copy link

Added pattern.

@{ Dictionary<string, object> values = new Dictionary<string, object>() { { "class", "text-box single-line" }, { "type", "text" } };
values.Add("placeholder", ViewData.ModelMetadata.Watermark);
if (ViewData.ModelMetadata.IsRequired) { values.Add("required", "required"); }
if (ViewData.ModelMetadata.IsReadOnly) { values.Add("readonly", "readonly"); }
if (ViewData["autofocus"] != null && ViewData["autofocus"].ToString().ToLower().Equals("autofocus")) { values.Add("autofocus", "autofocus"); }
IEnumerable rules = ModelValidatorProviders.Providers.GetValidators(ViewData.ModelMetadata, ViewContext).SelectMany(x => x.GetClientValidationRules());
ModelClientValidationRule lengthRule = rules.FirstOrDefault(x => x.ValidationType.ToLower().Equals("length"));
if (lengthRule != null && lengthRule.ValidationParameters.ContainsKey("max")) { values.Add("maxlength", lengthRule.ValidationParameters["max"]); }
ModelClientValidationRule rangeRule = rules.FirstOrDefault(x => x.ValidationType.ToLower().Equals("range"));
if (rangeRule != null && rangeRule.ValidationParameters.ContainsKey("min")) { values.Add("min", rangeRule.ValidationParameters["min"]); }
if (rangeRule != null && rangeRule.ValidationParameters.ContainsKey("max")) { values.Add("max", rangeRule.ValidationParameters["max"]); }
ModelClientValidationRule regexRule = rules.FirstOrDefault(x => x.ValidationType.ToLower().Equals("regex"));
if (regexRule != null && regexRule.ValidationParameters.ContainsKey("pattern")) { values.Add("pattern", regexRule.ValidationParameters["pattern"]); }
}
@Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, values)

@paultyng paultyng closed this Sep 9, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants