November Happy Hour will be moved to Thursday December 5th.

Dojo custom property editor not auto saving?

Vote:
 

Hey Guys,

So i've developed a dojo editor for a string property that basically makes a multiselect autocomplete and stores the value in the string as a comma seperated list.  Everything is working properly (control shows, value setters are hit, although no values exist because its not being saved, events are hit, this.OnChange is hit and bubbles up to the epi widgets) but the value never saves, stepping through the unminified epi js code, I see where it should be doing a .save but it never hits.  In one portion of the code i saw where it as evualating 3 coditions, one of which was this.editing, this was false, which sent it past the .save call...

I've included my dojo code below.. a note, I had to use a jquery plugin (select2) to get the interface i desired, since nothing like this exists for dojo or nobody has created a working version.  Again, this loads fine, and works, no issues with jquery, no issues with the values being set on the input it changes into the "fancy multiselect autocomplete" - the only issue is the autosave never happens...

Dojo Code:

define([
        "dojo/_base/declare",
        "dojo/_base/lang",
        "dijit/_Widget",
        "dijit/_TemplatedMixin",
        "epi/shell/widget/_ValueRequiredMixin",
        "epi/epi",
        "dojo/text!phoenixweb/Editors/templates/tobeditor.html"
], function (
    declare,
    lang,
    _Widget,
    _TemplatedMixin,
    _ValueRequiredMixin,
    epi,
    template) {

    return declare([_Widget, _TemplatedMixin, _ValueRequiredMixin], {
        templateString: template,
        intermediateChanges: false,
        value: null,

        postCreate: function () {
            // call base implementation            
            this.inherited(arguments);

            //alert(this.foo);

            $(this.inputWidget).select2({
                placeholder: "Search for and add TOBs",
                minimumInputLength: 1,
                multiple: true,
                ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
                    'url': "http://10.0.1.239:8080/solr/yppa/select",
                    'dataType': 'jsonp',
                    'data': function (term, page) {
                        return { 'wt': 'json', 'q': '*' + term + '*', 'rows': 30 }
                    },
                    params: { 'jsonp': 'json.wrf' },
                    results: function (data, page) {
                        var resultData = data.response.docs;
                        var resultsFormatted = [];

                        for (var i = 0; i < data.response.docs.length; i++) {
                            resultsFormatted.push({ 'id': data.response.docs[i].yppacode, 'text': data.response.docs[i].yppatext });
                        }

                        return { results: resultsFormatted };
                    }
                }
            }).on("change", lang.hitch(this, this._onInputWidgetChanged));
        },

        isValid: function () {
            // summary:
            //    Check if widget's value is valid.
            // tags:
            //    protected, override

            return !this.required || this.value != "";
        },

        // Setter for value property        
        _setValueAttr: function (value) {
            this.inputWidget.value = value;
            this._set("value", value);
        },

        _setReadOnlyAttr: function (value) {
            this._set("readOnly", value);
            this.inputWidget.readOnly = value;
        },

        // Event handler for the changed event of the input widget        
        _onInputWidgetChanged: function (e) {
            this._updateValue(e.val);
        },

        _updateValue: function (value) {
            if (this._started && epi.areEqual(this.value, this.inputWidget.value)) {
                return;
            }

            this._set("value", this.inputWidget.value);
            this.onChange(this.inputWidget.value);
        }
    });
});

    

#71890
May 31, 2013 11:12
Vote:
 

So after stepping through tons and tons of epi js code, I found out that the this.editing is being set (what appears to be) when the widget is focused.  It does set editing to true, but when attaching to the "change" event, the startediting function of the _EditorWrapperBase js file gets hit after my onChange call happens.  therefor, for some reason this.editing in _EditorWrapperBase is false.  

This all works if i fire my _onInputWidgetChanged on a blur event for the select2 box.  I'm not sure why or how that's possible, but the auto save happens when i blur the select2...  I'd like to be able to do this on the change event of select2 because it fires whenever a selection is added or removed...

I'm guessing the this.editing issue is because stopEditing of _EditorWidgetBase happens when i select an option from the dropdown that is created (maybe the select2 is getting blurred when i click the selection, causing stopEditing to fire, then the Change event of select2 happens, then the re-focus of the textbox happens, causing the startEditing to fire.. I wish i could define in my widget when startediting and stopediting happen. or at least override default functionality.

Anyone have any ideas?

#71934
Jun 01, 2013 8:28
Vote:
 

I've fixed together a hacky solution, hopefully someone is able to respond with another option

I added 

setTimeout(lang.hitch(this, function () {
     this.onChange(value);
}), 50);

around the OnChange call with a small timeout, this appears to work, as this.editing for the wrapper base gets set to true before this gets called.

I've also added a blur listener to select2 to call the onChange as well as an added measure just in case this save doesn't fire for whatever reason (since it is hacky)

Does anyone know of a better way to do this, or a way to set this.editing for the wrapper base before my onChange call?  I am really skeptical of my solution.

#71935
Jun 01, 2013 10:22
Vote:
 

So, this solution isn't working 100% - i'm having intermittent issues with editors not seeing the value save (perhaps they are too quick sometimes and the timeout didn't occur to call change, etc)  what i would really like, is a way to force epi to save, regardless of the this.editing check in the base widget class, or at least force editing to be true on the field.

I'm in dire need of a better solution, please help :(

#72054
Jun 06, 2013 20:20
Vote:
 

Hi,

I'haven't used the Select2 widget but I'm guessing it opens a "dialog" of some sort when you click on it, and therefor your dojo widget looses focus. 

 

If that is the case you can try to mixin the "epi-cms/widget/_HasChildDialogMixin" on your widget and set the this.isShowingChildDialog to true when the Select2 widgets displays it's options. By setting the isShowingChildDialog to true the dojo widgets does not fire the onBlur event when it looses focus. 

#72066
Jun 07, 2013 15:05
Vote:
 

Hey Magnus,

Not a dialog, but yes you are correct, when the autocomplete drop down opens and the user clicks on a selection, I beileve the focus is lost on the widget instance which in turn probably fires the onblur and sets editing to false (sometimes stepping through the js doesn't yield the exact same results) but if a user hits enter or uses arrow keys to select something, usually the onChange firing will allow the autosave to go through.

I'm going to give the isShowingChildDialog a whirl when the dropdown opens and closes and see if that allows me to get around the saving issues i'm having.

Thanks!

#72067
Jun 07, 2013 16:13
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.