So I have a form working quite well with MVC 3, DataAnnotations and Unobtrusive javascript. However, I want to put a "watermark" on my input fields so that for example, the First Name textbox is populated with a value of "First Name" by default. When the user clicks on it, the value disappears and if they move off the field without entering anything, "First Name" appears again. Also, I have this implemented and working well.
My question has to do with the [Required] attribute on the FirstName property of my view model. If the user submits the form, by default that field has "First Name" in it so it passes the "Required" validation.
What's the best way to deal with this...I'm thinking of a few options:
1) Inject some jQuery to fire before the unobtrusive JS validation that clears the watermarks so that when the validation fires, those fields that have default values in them are blank. I'm not sure this is possible. Can you somehow inject a function before unobtrusive JS runs its validation?
2) Modify the [Required] attribute or create a new one to accept a default value and then compare it to see if they match. This raises a few issues in that I now have my default value specified in multiple places, one in the UI and one in code and that feels wrong.
3) Create a new "Watermark" attribute that I decorate a property with that specifies the default value for that field. Create a new HTML helper (instead of TextBoxFor) that looks for this attribute and emits the appropriate attributes to the tag. Modify or create a new [Required] attribute that looks for the existence of [Watermark] on the same field. This keeps the "Default value" in one place and keeps with DRY principles, but it feels like I'm putting UI elements into code (watermarks are purely visual) and it also feels like an overly complex solution for what should be a simple issue.
Any thoughts?
Each has it's pros/cons. I like to keep this client side and have used the following.
Use the HTML5 placeholder attribute and for browsers that support it you don't have to do anymore.
<input type="text" placeholder="First name" />
For browsers that don't...
On every page we have some compatability script for browsers that don't support certain features. In this case it's a little bit of JavaScript and jQuery that detects if the browser supports the placeholder attribute. If it doesn't it sets the field value to the placeholder value, sets the styling and adds the appropriate focus/blur event handlers. The focus/blur event handlers set the field value appropriately.
Then on your client validation script check that field value doesn't equal the placeholder value.
In your case this would mean modifying your unobtrusive JS validation to check the field value doesn't equal the placeholder value
I would probably go with #2, I think you could go about doing this in such a way that you do not need to specify the default value more than once. Also, if you wanted to validate that a user name was not taken you could use remote validation and then just check if the name was already taken or was the default name so you could get the behavior you wanted for free.
Related
I have a form that asks a user for their first name, last name, phone number, ID number, username, and check boxes to choose either faculty or student in that order. The first two text boxes have two validators each, a regular expression: ^[a-zA-Z- ]*$ and required field validator. After that I created some custom validators as in addition to the text box for phone number, ID number, and username I have a "Don't know?" checkbox in case they forgot. So it validates to make sure they either typed in something and if not to make sure the check box is checked. Now, if I fire up the site and simply click the confirm button only the first two fields trigger their validation, that is the first and last name fields. Now, if I put in a first and last name and click confirm button again the rest of the validators trigger as normal. How can I get them to all trigger at once? Thanks.
Your custom validator logic may be implemented only in server side. You may have to provide the validation logic at client side by writing a javascript method and specifying it in ClientValidationFunction property. The link also provides an example on how to implement it in the client side.
I am building a search form which needs multiple fields. A radio button indicates which fields are required for input like so :
[ ] Field 1
[.] Field 2
Field 3
[ ] Field 4
In the above case, Field 2 and Field 3 are now required since the associated radio button is checked. To accomplish this, I have implemented the RequiredIf validation attribute, and it works properly.
My problem are the other validations. In this case, Field 1 also has a minimum length validation. If Field 1 has any value that does not respect the minimum length validation, the form is now invalid and cannot be submitted.
I need a way to disable validation on the fields that are not required. (And also be able to set them back as another radio button is checked).
The fields cannot be set to "disabled=disabled" which solves the issue because of client requirements.
I have tried removing the data-val attributes or setting them to false on the said fields, then parsing my form again, failing miserably.
Edit: Just making sure. The problem is client-side validations.
Remember that there are 2 validations happening: client and server side. Hence, removing the data-val attribute will not help.
Now, in your models I reckon you are using [attributes] to add these validation rules. I don't think this method will not let you do conditional validations.
In this case FluentValidation can help you. http://fluentvalidation.codeplex.com/
It is quite simple to do, and you should be able to do something like:
RuleFor(model => model.Field).NotEmpty().When(model => model.FieldEnabled);
Setting the fields as "disabled" works as intended. The client has changed his mind about this requirement. Sometimes it is the best solution.
This is still open for better solutions.
Edit :
I had not thought about searching for doc on the validation plugin. There seems to be some pretty interesting methods available to use like rules ( "remove", rules ).
I am just a bit stuck with Custom Validation. I have created a web page under which I have applied custom Validation on different fields like firstName, LastName etc...However, when I try to apply custom validation on a field which does not contains any value, the custom validation does not get fired, whether it is on Client Side or Server Side. I tried to find the answer to this as to why this was happening and I came to know that Custom Validation cannot be applied to field which does not contains any value.
However, this can be done with Required Field Validator.
I want to achieve that if First Name and Last Name are entered by the User, then they should enter Address too, making it mandatory. When I tried custom Validation on Address textbox, it does not get fired. Please help
Set the ValidateEmptyText property to true.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.customvalidator.validateemptytext.aspx
Is it possible to have "Required Field Validator" controls to validate more than one field (example I have 12 textboxes that are required. I want to try an avoid having 12 RFV controls. If a validation does get triggered, is there a way to display a customized message ("textA is empty" or "textB is empty") etc.?
You can create a custom validator that goes through validates all the controls.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.customvalidator.aspx
The Required Field Validator can only validate one control at a time.
You cannot do that with a RequiredFieldValidator; you could write your own CustomValidator to do that, but the validation would be on the server side rather than on the client side.
Multiple Fields Validator - An ASP.NET Validation Control is what you need.
As mentioned by everyone else you can create your CustomValidator that can validate on the client side and on the server side. There are couple of things that you must keep in mind.
1) Make sure to expose your client script as a Web Resource. This will enable the script to be cached by the browser.
2) Use a certain attribute to target certain TextBoxes. This can be performed by giving them a certain class which will be validated in your Custom Validator control.
Hope it helps!
I have a disabled TextBox that I am editing the value of on the client side with JavaScript. When I try to retrieve the value on the server side it does not reflect the change made on the client side. If I set the TextBox's enabled attribute to true I can retrieve the value, but the user is able to put focus and edit the TextBox.
Is there a sane way to keep the user from giving focus and editing to the TextBox?
Use the textbox's ReadOnly property.
Edit: Based on OP's comment, this will probably not do the trick then.
Edit 2: From DotNetSlackers:
So what's the difference between these
two properties and why do both exist?
There are two differences between
these two properties, a trivial
difference and a subtle, profound one:
The two properties emit different markup. When you set Enabled
to False, the TextBox injects the
attribute disabled="disabled" intoits
rendered HTML. When you set the
ReadOnly property to True, the
attribute readonly="readonly" is
injected.
According to the W3C spec on HTML forms, disabled controls areNOT
"successful," while read-only controls
MAY BE "successful." A "successful"
control is one whose name/value pair
is sent back to the browser through
the POST headers or querystring.
Therefore, disabled controls are NOT
sent back to the ASP.NET page, while
read-only controls may be, depending
on the User Agent. (In my tests,both
IE 6and FireFox 1.5 send along the
read-only TextBox input.)
......
If you encountered this problem in
ASP.NET version 1.x you might have
found the TextBox's ReadOnly property
and used that instead of setting
Enabled to False. You could still have
a page's ViewState disabled and set a
read-only TextBox Web control's Text
property programmatically because the
TextBox value is sent back through the
form submission for read-only
controls. However, in ASP.NET version
2.0, things change just a bit, as noted by Rick Strahlin his blog entry
ASP.NET 2.0 ReadOnly behavior change
when EnableViewState is false. With
2.0, the TextBox control'sReadOnly property's behavior has changed
slightly. From the technical docs:
The Text value of a TextBox control with the ReadOnly property set to true is sent to the server when a postback occurs, but the server does no processing for a read-only text box. This prevents a malicious user from changing a Text value that is read-only. The value of the Text property is preserved in the view state between postbacks unless modified by server-side code.
What happens is that the client sends
along the value of the read-only
TextBox through the form values, but
the ASP.NET 2.0 engine does not take
that value and assign it to the Text
property of the TextBox on postback to
help protect against a malicious user
changing the read-only TextBox value
themselves. But this brings us back to
our earlier problem - if the value
isn't specified in the postback (or is
ignored, in this case) and ViewState
is disabled, the value will be lost.
Eep.
Rick'sworkaround was to just manually
read the value from the request
headers (this .TextBox1.Text =
Request[this.TextBox1.UniqueID];),
which poses a security risk and
introduces the problem that 2.0
addresses. The optimal approach is to
requery the value from the database
(or wherever you initially got the
programmatically-set value for the
read-only TextBox).
The moral of this blog post is that if
you have read-only data you can use
either disabled or read-only form
fields, it really doesn't matter
whether or not you receive back the
value of the form field in the form's
submissions. It shouldn't matter
because you shouldn't be
trusting/using that data to begin
with! If you have read-only data,
don't re-read it from a data stream
that the end user can tinker with!
Source
Browsers don't post values back in disabled input controls, as you've discovered. Probably the easiest way to work around this is to hook onto form submission, and re-enable the input as the form is being submitted; the user won't have a chance to edit the value, and it should get posted with the rest of the request.
An alternative might be to inject a hidden element into the form; this could either be maintained by your script, mirroring the displayed value, or added at the end, in a similar fashion to the above.