Hi Andreas,
I think you need to change "_setValueAttr" to be like:
_setValueAttr: function(val) { this._set("value", val); }
Reference: http://world.episerver.com/documentation/Items/Developers-Guide/EPiServer-CMS/7/Editing/How-To/Creating-an-Editor-Widget/
Aria
Hi Aria,
Please correct me if I'm wrong but I'm pretty sure _setValueAttr()'s purpose is to populate the UI with the value stored in the database on prorpety-load.
You are very correct but the point is save happen based on "value" which is not set already. Whenever you click on "Publish" or "Auto Save" happens the "value" becomes "undefined" and nothing will be saved! Maybe I'm wrong but it worth to take a look ... or perhaps add this:
_setValueAttr: function(val) { this._set("value", val); alert(val); }
To see if the value is correct or not. Let us know what is the value of "val".
Aria
Thanks for the information. If I manually set an object in my BackingType-class to send in the Value.Get I see that this value is present in the _setValueAttr()-val parameter. So that part works fine. But when I hit toggleContact() and hardcode a new value and triggers a change with
this._set('value', model); this.onChange(model);
Hi mate,
Take a look again on the code seems like
toggleContact: function() { var model = { HSAID: 'johan189', UseExternalContactInformation: false, FullName: '', Email: '', Phone: '' }; this._set('value', model); this.onChange(model); },
asddasadsasd
Is not going to work. Dojo will break down on complex type. So you need to change backing type to be "string" and convert data from string to JSON object and when saving other way around. Good sample would be https://andersnordby.wordpress.com/2014/10/24/creating-a-custom-property-with-a-dojo-widget/
Aria
Hmm, I don't think I understand 100% (I think that I have implemented my backend much like the blog you linked). I'll give you what I got so far. The property ->
[UIHint(HSAOrExternalContactInformationEditorDescriptor.UIHint)] [BackingType(typeof(PropertyHSAOrExternalContactInformation))] public virtual HSAOrExternalContactInformation ContactInformation { get; set; }
The editor descriptor ->
[EditorDescriptorRegistration(TargetType = typeof(HSAOrExternalContactInformation), UIHint = HSAOrExternalContactInformationEditorDescriptor.UIHint)] public class HSAOrExternalContactInformationEditorDescriptor : EditorDescriptor { public const string UIHint = "HSAOrExternalContactInformation"; private const string hsaOrExternalContactInformationProperty = "intra/editors/HSAOrExternalContactInformationProperty"; public HSAOrExternalContactInformationEditorDescriptor() { ClientEditingClass = hsaOrExternalContactInformationProperty; } }
The backing type class ->
[PropertyDefinitionTypePlugIn()] public class PropertyHSAOrExternalContactInformation : PropertyLongString { public override Type PropertyValueType { get { return typeof(HSAOrExternalContactInformation); } } public override object Value { get { var value = base.Value as string; if (value == null) { return null; } var serializer = new JavaScriptSerializer(); return serializer.Deserialize(value, typeof(HSAOrExternalContactInformation)); } set { if (value is HSAOrExternalContactInformation) { var serializer = new JavaScriptSerializer(); base.Value = serializer.Serialize(value); } else { base.Value = value; } } } public override object SaveData(PropertyDataCollection properties) { return LongString; } }
Do I handle serialization/deserialization differently to what you mean? Thanks for the help!
Sorry for confusion. working version:
define([ "dojo/_base/declare", "dijit/_Widget", "dijit/_TemplatedMixin", 'dojo/text!./templates/HSAOrExternalContactInformationProperty.html', "dojo/dom", "dojo/domReady!" ], function ( declare, _Widget, _TemplatedMixin, template, dom ) { return declare("intra/editors/HSAOrExternalContactInformationProperty", [ _Widget, _TemplatedMixin], { templateString: template, value: null, postCreate: function () { this.inherited(arguments); }, _onChange: function (event) { if (!this.value) { this.value = { hSAID: '', fullName: '' }; } this.value.fullName = event.target.value this._set('value', this.value); this.onChange(this.value); }, _setValueAttr: function (val) { this.fullName.value = val.fullName; this._set('value', val); }, isValid: function () { return true; } } ); });
I assume the HTML is:
<div> <input type="text" data-dojo-attach-point="fullName" data-dojo-attach-event="onchange:_onChange" /> </div>
and c#:
[EditorDescriptorRegistration(TargetType = typeof(HSAOrExternalContactInformation), UIHint = HSAOrExternalContactInformationEditorDescriptor.UIHint)] public class HSAOrExternalContactInformationEditorDescriptor : EditorDescriptor { public const string UIHint = "HSAOrExternalContactInformation"; private const string hsaOrExternalContactInformationProperty = "alloy/editors/HSAOrExternalContactInformationProperty"; public HSAOrExternalContactInformationEditorDescriptor() { ClientEditingClass = hsaOrExternalContactInformationProperty; } } [PropertyDefinitionTypePlugIn()] public class PropertyHSAOrExternalContactInformation : PropertyLongString { public override Type PropertyValueType { get { return typeof(HSAOrExternalContactInformation); } } public override object Value { get { var value = base.Value as string; if (value == null) { return null; } var serializer = new JavaScriptSerializer(); return serializer.Deserialize(value, typeof(HSAOrExternalContactInformation)); } set { if (value is HSAOrExternalContactInformation) { var serializer = new JavaScriptSerializer(); base.Value = serializer.Serialize(value); } else { base.Value = value; } } } public override object SaveData(PropertyDataCollection properties) { return LongString; } } public class HSAOrExternalContactInformation { public string HSAID { get; set; } public string FullName { get; set; } }
and actual usage would be:
[UIHint(HSAOrExternalContactInformationEditorDescriptor.UIHint)] [BackingType(typeof(PropertyHSAOrExternalContactInformation))] public virtual HSAOrExternalContactInformation ContactInformation2 { get; set; }
Thanks for the help Aria,
After changing to handle one value at a time it works :)
I'm creating a custom dojo-widget, much like this blog post -> http://www.patrickvankleef.com/2015/02/03/episerver-custom-property-in-dojo/ where I save the serialized object as a string by implementing a BackingType-class to handle (de)serialization. On the client side I have created a very bare class so far since I can't get the save-request to fire and hit my BackingType-class Value.Set property. I have this dojo-code so far.
The first question I have is, what should trigger a call to the backend to save my object? The second question is, isn't it the _getValueAttr() or this.onChange() that SHOULD trigger a save-request?
Thanks for the help!