vitalets / x-editable

In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
http://vitalets.github.io/x-editable
MIT License
6.51k stars 1.72k forks source link

xeditable & select2 dropdown w/ajax source displaying empty after submitting #1056

Open ihelmer07 opened 6 years ago

ihelmer07 commented 6 years ago

I've gotten xeditable and select2 to work with an ajax api call as the source and everything works great EXCEPT the following.

After submitting the select2 dropdown, the value of the table is displayed as EMPTY and requires a page refresh in order to update to the correct value.

Does anyone know how to update the value to the selected select2 dropdown value?

my html:

<td class="eo_role"><a href="#" data-pk={{r.pk}} data-type="select2" data-url="/api/entry/{{r.pk}}/"
data-name="eo_role" data-title="Enter EO_role">{{r.eo_role}}</a></td>

my js:

$('#example .eo_role a').editable( {
    params: function(params) {  //params already contain `name`, `value` and `pk`
      var data = {};
      data[params.name] = params.value;
      return data;
    },
    source: 'http://localhost:8000/api/eo_role/select_two_data/',
    tpl: '<select></select>',
    ajaxOptions: {
        type: 'put'
        },
    select2: {
        cacheDatasource:true,
        width: '150px',
        id: function(pk) {
            return pk.id;
        },
        ajax: {
            url: 'http://localhost:8000/api/eo_role/select_two_data/',
            dataType: "json",
            type: 'GET',
            processResults: function(item) {return item;}    
        }
    },
    formatSelection: function (item) {
        return item.text;
    },
    formatResult: function (item) {
        return item.text;
    },
    templateResult: function (item) {
        return item.text;
    },
    templateSelection : function (item) {
        return item.text;
    }, 
});

Stack Overflow Question

ihelmer07 commented 6 years ago

i don't know how to add "discuss" tag.

ihelmer07 commented 6 years ago

The issue has been traced to here - the 'data' variable is not being set, and the value selected is the ID of the json query and somehow we need to translate that to the text. Not sure how to do that.

$.extend(Constructor.prototype, {
        render: function() {
            this.setClass();

            //can not apply select2 here as it calls initSelection 
            //over input that does not have correct value yet.
            //apply select2 only in value2input
            //this.$input.select2(this.options.select2);

            //when data is loaded via ajax, we need to know when it's done to populate listData
            if(this.isRemote) {
                //listen to loaded event to populate data
                ////****THIS IS NOT SETTING SOURCEDATA*****
                this.$input.on('select2-loaded', $.proxy(function(e) {
                    this.sourceData = e.items.results;
                }, this));
            }

            //trigger resize of editableform to re-position container in multi-valued mode
            if(this.isMultiple) {
               this.$input.on('change', function() {
                   $(this).closest('form').parent().triggerHandler('resize');
               });
            }
       },

       value2html: function(value, element) {
           var text = '', data,
               that = this;

           if(this.options.select2.tags) { //in tags mode just assign value
              data = value; 
              data = element.outerText;
              //data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);

              //was this.sourceData
           } else if(this.sourceData) {
              data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc); 
           } else {
              //can not get list of possible values 
              //(e.g. autotext for select2 with ajax source)
           }

           //data may be array (when multiple values allowed)
           if($.isArray(data)) {
               //collect selected data and show with separator
               text = [];
               $.each(data, function(k, v){
                   text.push(v && typeof v === 'object' ? that.formatSelection(v) : v);
               });
           } else if(data) {
               text = that.formatSelection(data);
           }

           text = $.isArray(text) ? text.join(this.options.viewseparator) : text;
           console.log(text);
           //$(element).text(text);
           Constructor.superclass.value2html.call(this, text, element); 
       },
ihelmer07 commented 6 years ago

Figured out a workaround!!!!! SUPER PUMPED!!!!


//outside of everything, EVERYTHING
//test object is a global holding object that is used to hold the selection dropdown lists
//in order to return the correct text.
var test = {};

    $('#example .eo_role a').editable( {
        params: function(params) {  //params already contain `name`, `value` and `pk`
          var data = {};
          data[params.name] = params.value;
          return data;
        },

        //MUST be there - it won't work otherwise.
        tpl: '<select></select>',
        ajaxOptions: {
            type: 'put'
            },
        select2: {

            width: '150px',
            //tricking the code to think its in tags mode (it isn't)
            tags:true,
            //this is the actual function that triggers to send back the correct text.
            formatSelection: function (item) {
                //test is a global holding variable set during the ajax call of my results json.
                //the item passed here is the ID of selected item. However you have to minus one due zero index array.
                return test.results[parseInt(item)-1].text;
            },
            ajax: {
                url: 'http://localhost:8000/api/eo_role/select_two_data/',
                dataType: "json",
                type: 'GET',
                processResults: function(item) {
                //Test is a global holding variable for reference later when formatting the selection.
                //it gets modified everytime the dropdown is modified. aka super convenient.
                test = item;
                return item;}    
            }
        },  
    });  
rauvolaj commented 6 years ago

This worked!