I'm creating my own custom datatype, but I don't know how to make it mandatory. If no value is selected I return null, but the data is still saved. Do I need to do something special to make my custom datatype mandatory?
Ok for now I just make sure the page isn't valid if no data has been selected. This makes it mandatory, but I only want to it be mandatory if the mandatory checkbox has been check on the documenttype property. How can I do this?
Ok I've found a solution to make my custom datatype mandatory, but there must be an easier way to do this:
//Get the current document.
Document document = new Document(Convert.ToInt32(Request.QueryString["id"]));
//Get all the propertytypes that use this datatype.
IEnumerable<PropertyType> propertyTypes = PropertyType.GetByDataTypeDefinition(DataTypeDefinitionId);
//Get the current propertytype:
PropertyType propertyType =
(
from property in propertyTypes
where property.ContentTypeId == document.ContentType.Id
select property
).Single();
if (propertyType.Mandatory)
{
//If the propertytype is mandatory show an error message.
DAMP_Validation.ShowError("This field is mandatory. That means you need to select at least 1 media item.");
}
Embarrassingly, I've just come across this too with uComponents!
Are you inheriting your data-type from the AbstractDataEditor class? As its looking like you can't associate a ValidationGroup attribute with the RenderControl property (which is using the AbstractDataEditorControl). I'm not 100% sure if this is the case - but currently looking into it!
I'm using the AbstractDataEditor class, but in the umbraco backend you don't need a ValidationGroup. It actually works if you don't pass a validation group because the save button uses validation but without a validation group. Here a sample which I use to throw an error:
CustomValidator cv = new CustomValidator();
cv.IsValid = false;
cv.ErrorMessage = message;
if (!string.IsNullOrEmpty(validationGroup))
{
cv.ValidationGroup = validationGroup;
}
Page currentPage = HttpContext.Current.Handler as Page;
currentPage.Validators.Add(cv);
There are easier ways to add an error to a page, but this sample supports a validation group (even if we don't need it in this situation).
In my third post I have the following piece of code at the bottom:
if(propertyType.Mandatory) { //If the propertytype is mandatory show an error message. DAMP_Validation.ShowError("This field is mandatory. That means you need to select at least 1 media item."); }
In the ShowError method I call the sample I gave in my fourth post with the CustomValidator. I'm also using this technique in the Digibiz Email Form with TinyMCE package. I could send you the source code if you're interessted.
I agree with you Jeroen - seems far too difficult to make a custom data-type mandatory. I wasn't too comfortable iterating over the Document's properties - felt like too much of an overhead. Hopefully there'll be a fix for v4.6 Juno!
To make a custom datatype mandatory you just have to follow .NET practices, which is making a validation attribute to your control class, where the parameter is the name of the property to test:
[ValidationProperty("Text")]
How could that be easier or am I missing something?
I haven't tried that yet. Will this make my custom datatype only mandatory if the mandatory checkbox is checked on the documenttype property which uses my custom datatype? That's the problem I'm having currently. It only needs to be mandatory if the user chose this on the documenttype.
If the property that you specify in the ValidationProperty returns something - then it's considered as filled out. So if it's marked mandatory, then it'll be approved. For good inspiration on this, check out the relatedlinks source:
I've tried the ValidationProperty attribute before, (and again now - to double check), but it doesn't work when inheriting from the AbstractDataEditor class.
Niels' example of the Related Links data-type inherits from BaseDataType (along with implementing the IDataType and IDataEditor interfaces).
My gut feeling is that something goes astray in the AbstractDataEditor class?
Ok I found another solution, but it's still not really easy. In the DataType there is a way to get the PropertyType. Here's how:
My IData can return DefaultData or DAMP_Data which returns xml. I need to show this sample so you can understand te rest of the code.
public override IData Data
{
get
{
if (this._data == null)
{
if (!StoreAsXML)
{
this._data = new DefaultData(this);
}
else
{
this._data = new DAMP_Data(this);
}
}
return this._data;
}
}
Here is how I get the PropertyType in my DataType which inherits from the AbstractDataEditor.
//Get the propertyId which we need to get the current PropertyType.
int propertyId = StoreAsXML ? ((DAMP_Data)this.Data).PropertyId : ((DefaultData)this.Data).PropertyId;
//Get the current PropertyType because we need the mandatory value.
PropertyType propertyType = new PropertyType(SqlHelper.ExecuteScalar<int>("select propertytypeid from cmsPropertyData where id = @id", SqlHelper.CreateParameter("@id", propertyId)));
//Store the mandatory value.
bool mandatory = propertyType.Mandatory
Now that I have the mandatory value I pass this value to my DataEditor where I can check if a field is mandatory and if anything has been filled in my custom control. Here is a sample:
if (mandatory && string.IsNullOrEmpty(TxtMessage.Text))
{
//If the propertytype is mandatory and the textbox is empty show an error message.
LitError.Text = "This field is mandatory";
LitError.Visible = true;
DAMP_Validation.ShowError(LitError.Text);
}
Here is my static DAMP_Validation method:
public static class DAMP_Validation
{
public static void ShowError(string message)
{
ShowError(message, string.Empty);
}
public static void ShowError(string message, string validationGroup)
{
CustomValidator cv = new CustomValidator();
cv.IsValid = false;
cv.ErrorMessage = message;
if (!string.IsNullOrEmpty(validationGroup))
{
cv.ValidationGroup = validationGroup;
}
ShowError(cv);
}
public static void ShowError(CustomValidator cv)
{
Page currentPage = HttpContext.Current.Handler as Page;
currentPage.Validators.Add(cv);
}
}
So with this code I can get the mandatory field in a DataType, pass it to the DataEditor and throw an error (making the page invalid) if mandatory is true and no value has been selected. Still hope there will be an easier solution for this in Umbraco v4.6 JUNO.
Here is a small update. The above code works, but there should be an extra check to see if the DataType is used on a custom section:
//Get the propertyId which we need to get the current PropertyType.
int propertyId = StoreAsXML ? ((DAMP_Data)this.Data).PropertyId : ((DefaultData)this.Data).PropertyId;
bool mandatory = false;
//Check if the propertyId is not 0. If it is this DataType is probably used in a custom section.
if (propertyId != 0)
{
//Get the current PropertyType because we need the mandatory value.
PropertyType propertyType = new PropertyType(SqlHelper.ExecuteScalar<int>("select propertytypeid from cmsPropertyData where id = @id", SqlHelper.CreateParameter("@id", propertyId)));
//If a PropertyType is returned store the mandatory field.
mandatory = propertyType.Mandatory;
}
And again I've got an improved version :). This version also gets the property name and on which tab the property is. This can be used for the mandatory message:
Code in the DataType:
//Get the propertyId which we need to get the current PropertyType.
int propertyId = StoreAsXML ? ((DAMP_Data)this.Data).PropertyId : ((DefaultData)this.Data).PropertyId;
bool mandatory = false;
//Check if the propertyId is not 0. If it is this DataType is probably used in a custom section and no PropertyType is available.
if (propertyId != 0)
{
//Get the current PropertyType because we need some property data.
PropertyType propertyType = new PropertyType(SqlHelper.ExecuteScalar<int>("select propertytypeid from cmsPropertyData where id = @id", SqlHelper.CreateParameter("@id", propertyId)));
//Store the mandatory field.
mandatory = propertyType.Mandatory;
//Get the name of the tab.
string tabCaption = SqlHelper.ExecuteScalar<string>("Select text from cmsTab where id = " + propertyType.TabId);
if(string.IsNullOrEmpty(tabCaption))
{
//If no tab is found this means it's on the default (Generic Properties) tab.
tabCaption = "Properties";
}
//Set the the mandatory text now that we have a property name and tab.
mandatoryText = string.Format("The {0} field in the {1} tab is mandatory", propertyType.Name, tabCaption);
}
Code in the DataEditor:
if (mandatory && string.IsNullOrEmpty(TxtMessage.Text))
{
//If the propertytype is mandatory and the textbox is empty show an error message.
LitError.Text = mandatoryText; LitError.Visible = true;
DAMP_Validation.ShowError(LitError.Text);
}
Now the mandatory message will look exactly like the default Umbraco mandatory message, but with complete control over the output so you can also change the mandatory message. I do this with my newest datatype because you can have a minimum and maximum node selection and those will give custom messages, but also in with the name and tab data.
You'll be pleased to know that this issue will be fixed in Juno (just comitted the fix), the abstract data editor will now respect the validationproperty
That's great news! Also good to hear the usercontrol wrapper can be mandatory. This in combination with the DataEditorSetting will make the usercontrol wrapper so much more powerfull!
Wow that's also cool! How does it detect if the usercontrol wrapper stores xml? Can you just return an XDocument or XmlDocument and it will be stored as xml or do you need to return a string which contains xml? With this I will use the abstract data editor a lot less because this is so much easier :D.
Did your changes also make it through Umbraco v 4.7.0 ?
Maybe I am doing something wrong here but the validation property does not seem to get fired during save/publish.
Here's what I did:
[ValidationProperty("IsValid")]
public partial class ScheduleEditor : System.Web.UI.UserControl,
umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor
public string IsValid
{
get
{
if (GetSchedule().IsValid)
return "Valid";
else
return String.Empty;
}
}
I'm debugging it locally and added a breakpoint inside the property and it does not get fired.
I have also tried returning a different type like bool or object, without any success.
Well when using the usercontrol wrapper the validation property is the value property, when that is null or en empty string it will be considered as not valid
That makes sense and indeed it works for a single value. When working with multiple values or XML data however, the value property does not allow for a partial result to be returned in order to support the mandatory setting (e.g. if the property is not mandatory the user should be able to save some of the data).
Is there perhaps another way of achieving this? Perhaps I can access the mandatory setting and return values based on that?
Well I guess in your custom object you know if you have valid values or not, can't you just return null or en empty string when it is empty? And don't return the serialized object in that case.
Yup, I got that working but when the property isn't mandatory I want to allow an "invalid" (partial) value to be saved.
For example lets say there are 2 values, and when the property is mandatory, both values need to be completed.
When the property is not mandatory however, I would allow the user to save just 1 value, but this is no longer possible as the validation would allow only to save a valid object or none. So it looks like I need a more complex logic to handle this, one way would be look at whether the property is mandatory or not..
Make custom datatype mandatory
Hello,
I'm creating my own custom datatype, but I don't know how to make it mandatory. If no value is selected I return null, but the data is still saved. Do I need to do something special to make my custom datatype mandatory?
Jeroen
Ok for now I just make sure the page isn't valid if no data has been selected. This makes it mandatory, but I only want to it be mandatory if the mandatory checkbox has been check on the documenttype property. How can I do this?
Jeroen
Ok I've found a solution to make my custom datatype mandatory, but there must be an easier way to do this:
Jeroen
Hey Jeroen,
Embarrassingly, I've just come across this too with uComponents!
Are you inheriting your data-type from the AbstractDataEditor class? As its looking like you can't associate a ValidationGroup attribute with the RenderControl property (which is using the AbstractDataEditorControl). I'm not 100% sure if this is the case - but currently looking into it!
I'll keep you posted if I have any news.
Cheers, Lee.
Hi Lee,
I'm using the AbstractDataEditor class, but in the umbraco backend you don't need a ValidationGroup. It actually works if you don't pass a validation group because the save button uses validation but without a validation group. Here a sample which I use to throw an error:
There are easier ways to add an error to a page, but this sample supports a validation group (even if we don't need it in this situation).
Jeroen
Hi Jeroen, where are you adding this validation code? (Trying to figure out how it all should piece together).
Thanks, Lee.
In my third post I have the following piece of code at the bottom:
In the ShowError method I call the sample I gave in my fourth post with the CustomValidator. I'm also using this technique in the Digibiz Email Form with TinyMCE package. I could send you the source code if you're interessted.
Jeroen
Thanks Jeroen, much appreciated!
It was a bit of a shock when I realised that the data-types in both my uComponents and uTube packages don't support the Mandatory option! :-(
Cheers, Lee.
I've been testing my sample code a bit more and unfortunately it still has some errors. For example the following line:
This works if you use the datatype only a 1 time on a documentype. If you use the datatype multiple times the following will not work:
This will result into multiple results so the .Single() will throw an error. Somehow we need to get more info to get the correct PropertyType.
Jeroen
I've added a workitem for it because currently I think making a custom datatype mandatory is too hard: http://umbraco.codeplex.com/workitem/29681. Please vote.
Jeroen
I agree with you Jeroen - seems far too difficult to make a custom data-type mandatory. I wasn't too comfortable iterating over the Document's properties - felt like too much of an overhead. Hopefully there'll be a fix for v4.6 Juno!
Cheers, Lee.
To make a custom datatype mandatory you just have to follow .NET practices, which is making a validation attribute to your control class, where the parameter is the name of the property to test:
[ValidationProperty("Text")]
How could that be easier or am I missing something?
Hi Niels,
I haven't tried that yet. Will this make my custom datatype only mandatory if the mandatory checkbox is checked on the documenttype property which uses my custom datatype? That's the problem I'm having currently. It only needs to be mandatory if the user chose this on the documenttype.
Jeroen
If the property that you specify in the ValidationProperty returns something - then it's considered as filled out. So if it's marked mandatory, then it'll be approved. For good inspiration on this, check out the relatedlinks source:
http://umbraco.codeplex.com/SourceControl/changeset/view/81625#905786
(this will also be used for the regexp validation configuration, btw)
Thanks! I will try it out and see if it works :).
Jeroen
I've tried the ValidationProperty attribute before, (and again now - to double check), but it doesn't work when inheriting from the AbstractDataEditor class.
Niels' example of the Related Links data-type inherits from BaseDataType (along with implementing the IDataType and IDataEditor interfaces).
My gut feeling is that something goes astray in the AbstractDataEditor class?
Cheers, Lee.
In that case the workitem (http://umbraco.codeplex.com/workitem/29681) should stay open until there's a good solution for this.
Jeroen
Ok I found another solution, but it's still not really easy. In the DataType there is a way to get the PropertyType. Here's how:
My IData can return DefaultData or DAMP_Data which returns xml. I need to show this sample so you can understand te rest of the code.
Here is how I get the PropertyType in my DataType which inherits from the AbstractDataEditor.
Now that I have the mandatory value I pass this value to my DataEditor where I can check if a field is mandatory and if anything has been filled in my custom control. Here is a sample:
Here is my static DAMP_Validation method:
So with this code I can get the mandatory field in a DataType, pass it to the DataEditor and throw an error (making the page invalid) if mandatory is true and no value has been selected. Still hope there will be an easier solution for this in Umbraco v4.6 JUNO.
Jeroen
Here is a small update. The above code works, but there should be an extra check to see if the DataType is used on a custom section:
Jeroen
And again I've got an improved version :). This version also gets the property name and on which tab the property is. This can be used for the mandatory message:
Code in the DataType:
Code in the DataEditor:
Now the mandatory message will look exactly like the default Umbraco mandatory message, but with complete control over the output so you can also change the mandatory message. I do this with my newest datatype because you can have a minimum and maximum node selection and those will give custom messages, but also in with the name and tab data.
Jeroen
Comment author was deleted
Hi,
You'll be pleased to know that this issue will be fixed in Juno (just comitted the fix), the abstract data editor will now respect the validationproperty
Cheers,
Tim
Woo hoo! Nice one Tim! Thanks.
Comment author was deleted
And also fixed it with the usercontrol wrapper (so you can make those datatypes mandatory as well)
Cheers,
Tim
Hi Tim,
That's great news! Also good to hear the usercontrol wrapper can be mandatory. This in combination with the DataEditorSetting will make the usercontrol wrapper so much more powerfull!
Jeroen
Comment author was deleted
Indeed, and if you save xml in the usercontrol wrapper it will detect it and won't add it inside a cdata section
Wow that's also cool! How does it detect if the usercontrol wrapper stores xml? Can you just return an XDocument or XmlDocument and it will be stored as xml or do you need to return a string which contains xml? With this I will use the abstract data editor a lot less because this is so much easier :D.
Jeroen
Comment author was deleted
Yup both methods should work (return xml as string or xmldocument)
Hey Tim,
Did your changes also make it through Umbraco v 4.7.0 ?
Maybe I am doing something wrong here but the validation property does not seem to get fired during save/publish.
Here's what I did:
I'm debugging it locally and added a breakpoint inside the property and it does not get fired.
I have also tried returning a different type like bool or object, without any success.
Am I missing something here?
Comment author was deleted
Hi Lennart,
Well when using the usercontrol wrapper the validation property is the value property, when that is null or en empty string it will be considered as not valid
Hi Tim,
That makes sense and indeed it works for a single value. When working with multiple values or XML data however, the value property does not allow for a partial result to be returned in order to support the mandatory setting (e.g. if the property is not mandatory the user should be able to save some of the data).
Is there perhaps another way of achieving this? Perhaps I can access the mandatory setting and return values based on that?
Hope this makes sense :-)
Comment author was deleted
Well I guess in your custom object you know if you have valid values or not, can't you just return null or en empty string when it is empty? And don't return the serialized object in that case.
Should do the trick
Yup, I got that working but when the property isn't mandatory I want to allow an "invalid" (partial) value to be saved.
For example lets say there are 2 values, and when the property is mandatory, both values need to be completed.
When the property is not mandatory however, I would allow the user to save just 1 value, but this is no longer possible as the validation would allow only to save a valid object or none. So it looks like I need a more complex logic to handle this, one way would be look at whether the property is mandatory or not..
how to check If property is set to mandatory I found it in
in html for rendering control.
is working on a reply...