Unable to actually send a save request in a custom DOJO-widget

Vote:
 

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.

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);
            },
            toggleContact: function() {
                var model = {
                    HSAID: 'johan189',
                    UseExternalContactInformation: false,
                    FullName: '',
                    Email: '',
                    Phone: ''
                };

                this._set('value', model);
                this.onChange(model);
            },
            _getValueAttr: function () {
                var jsonObject = {
                    HSAID: 'johan189',
                    UseExternalContactInformation: false,
                    FullName: '',
                    Email: '',
                    Phone: ''
                };

                return jsonObject;
            },
            _setValueAttr: function (val) {

            },
            isValid: function () {
                return true;
            }
        }
    );
});

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!

#170681
Oct 26, 2016 10:29
Vote:
 

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

#170709
Oct 27, 2016 6:49
Vote:
 

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. 

#170711
Oct 27, 2016 7:58
Vote:
 

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
#170712
Oct 27, 2016 8:14
Vote:
 

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);
nothing happens. The same behavior (nothing happens with this.onChange() later) when _setAttrVal() returns a null value.
#170714
Edited, Oct 27, 2016 8:40
Vote:
 

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

#170724
Oct 27, 2016 10:45
Vote:
 

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!

#170726
Oct 27, 2016 13:06
Vote:
 

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; }
#170732
Oct 27, 2016 16:02
Vote:
 

Thanks for the help Aria,

After changing to handle one value at a time it works :)

#170733
Oct 27, 2016 17:15
Vote:
 

Happy it helps. 

#170738
Oct 27, 2016 21:35
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.