select field behavior

select field behavior

rf1234rf1234 Posts: 3,021Questions: 88Answers: 421

I noticed some unexpected behavior of "select" and "selectize" fields.
In case you add options to those fields later, e.g. on "open" or "opened" the field content is empty when you open Editor. Is that because on initialization of Editor there weren't any options? So that the field content couldn't be matched by an option?

This behavior only occurs if I edit a record right after page refresh. If I open the same record again, the field content is still there: Probably because the options were added on the previous editing.

Is that what it is supposed to be? I found this behavior quite weird and it was difficult for me to find a work around.
The work around is that I clear the field and add it back to the form on "initEdit".

Here is my code:
The field definition. Just a normal selectize field with no initial options

}, {
    label: lang === 'de' ? 'Federführende Abteilung:' : 'Leading Department:',
    name:  "sub.leading_ctr_govdept_id",
    type: "selectize",
    opts: {
        create: false,
        maxItems: 1,
        openOnFocus: true,
        allowEmptyOption: true,
        placeholder: 'optional'
    }
}, {

The event handler on "opened": self.val('sub.leading_ctr_govdept_id') is empty if I edit the record after a page refresh!

editor
    .on('opened', function(e, type, action) {  
        var self = this;
        $( self.field('ctr_govdept[].id').node() ).change( function() {
            //set the options for leading department based on the selected department(s)
            //if the value of the leading department is no longer among the 
            //selected departments the field value is empty
            var opts = $.extend(true, [], ctrGovdeptOptions);
            var selectedDeptsArray = $.grep(opts, function(obj) {
                return $.inArray(obj.value, self.val('ctr_govdept[].id')) >= 0; //only selected depts as options
            });
            var selectedDeptsIds = selectedDeptsArray.map(function(a){return a.value;});
            if ( $.inArray(self.val('sub.leading_ctr_govdept_id'), selectedDeptsIds) < 0 ) {
                self.set( {'sub.leading_ctr_govdept_id': ""} );
            }
            self.field('sub.leading_ctr_govdept_id').update(selectedDeptsArray);
        });
        $( self.field('ctr_govdept[].id').node() ).change();
    })
    .on('close', function() {
        $( this.field('ctr_govdept[].id').node() ).off( 'change' );
    })

My work around to make this work when editing. I don't have to do this for "create" because there the field content is empty initially anyway ...

editor
    .on('initEdit', function ( e, node, data, items, type ) {
        //must be reinitialized with all dept options because otherwise there are no options - and nothing is shown!!
        this.clear( "sub.leading_ctr_govdept_id" );
        this.add( {
            label: lang === 'de' ? 'Federführende Abteilung:' : 'Leading Department:',
            name:  "sub.leading_ctr_govdept_id",
            type: "selectize",
            options: ctrGovdeptOptions,
            opts: {
                create: false,
                maxItems: 1,
                openOnFocus: true,
                allowEmptyOption: true,
                placeholder: 'optional'
            }
        }, "ctr_govdept[].id" );
    })

This is how I get the options dynamically on "select". ctrGovdeptOptions is a global variable.

table
    .on ( 'select', function (e, dt, type, indexes) {
        $.ajax({
            type: "POST",
            url: 'actions.php?action=getCtrGovdeptOptions',
            data: {
                ctr_id: selected.data().ctr.id
            },
            dataType: "json",
            success: function (data) {   
                ctrGovdeptOptions = data.options
            }
        });
    })

This question has accepted answers - jump to:

Answers

  • allanallan Posts: 63,676Questions: 1Answers: 10,497 Site admin

    In case you add options to those fields later, e.g. on "open" or "opened" the field content is empty when you open Editor. Is that because on initialization of Editor there weren't any options? So that the field content couldn't be matched by an option?

    If I've understood "empty" correctly, then yes, that is exactly what it is. (I'm taken "empty" to mean that no value is selected, rather than there being no options listed?).

    Editor will do the edit operation in this order:

    1. Read values from the data source
    2. Set the values
    3. Do initEdit
    4. Do open

    There is code in the select control that should handle this - when the new options are loaded, the value that was last attempted to be set would be attempted again. The Selectize plugin doesn't have any code to handle that at the moment.

    Btw, Editor 2.4 isn't far away and it will have a built in auto complete like ability along the lines of Select2 and Selectize :).

    Allan

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421
    edited December 9

    If I've understood "empty" correctly, then yes, that is exactly what it is. (I'm taken "empty" to mean that no value is selected, rather than there being no options listed?).

    Let me be more detailed. Let's assume the value selected when creating the record was 1 (value from the label-value pair with label "whatever"). 1 is loaded from the server as the field content. I can see it in the browser's console.

    When trying to edit the field later without initial options (the options are only being added on "opened") Editor empties the field. It does no longer contain 1 but just nothing. I could observe this behavior in the debugger. The only workaround for me is to "clear" and "add" the field again with the options: Then Editor loads the field content of 1 again from what was sent from the server - and can match the 1 with an existing option's value.

    Hence, I believe: Editor deletes the field content if unable to match with an existing option. And I think that is undesirable. Let's assume Editor wouldn't delete the field content: Since the options are not loaded on initialization, but later, the missing options would mean that the label potentially couldn't be displayed in the select or selectize field. Only 1 could be displayed, not "whatever" - at least until the execution of the "opened" event. Maybe that's the reason? Don't know.

  • allanallan Posts: 63,676Questions: 1Answers: 10,497 Site admin
    Answer ✓

    Editor's built in select should be able to handle that already. I've just created this little example to demonstrate it. Notice that the office_value field is a select and it doesn't have any options set until open. When that happens, the options are set. It only really demonstrates that it can hold the current value at the start (since the options are present after that), but if I've understood correctly, that is what you are looking for?

    The Selectize plugin, I've just checked, doesn't have any code to handle such a case.

    Allan

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421

    Thanks for pointing that out, Allan! I still have an older version of Editor and also want to keep using selectize. So I will have to live with the work around for the time being.

    Are there any plans to update the selectize plugin as well? (I am afraid I am not good enough a coder to do this myself :neutral: )

  • allanallan Posts: 63,676Questions: 1Answers: 10,497 Site admin
    Answer ✓

    Try this:

    (function( factory ){
        if ( typeof define === 'function' && define.amd ) {
            // AMD
            define( ['jquery', 'datatables', 'datatables-editor'], factory );
        }
        else if ( typeof exports === 'object' ) {
            // Node / CommonJS
            module.exports = function ($, dt) {
                if ( ! $ ) { $ = require('jquery'); }
                factory( $, dt || $.fn.dataTable || require('datatables') );
            };
        }
        else if ( jQuery ) {
            // Browser standard
            factory( jQuery, jQuery.fn.dataTable );
        }
    }(function( $, DataTable ) {
    'use strict';
     
     
    if ( ! DataTable.ext.editorFields ) {
        DataTable.ext.editorFields = {};
    }
     
    var _fieldTypes = DataTable.Editor ?
        DataTable.Editor.fieldTypes :
        DataTable.ext.editorFields;
     
     
    _fieldTypes.selectize = {
        _addOptions: function ( conf, options ) {
            var selectize = conf._selectize;
     
            selectize.clearOptions();
            selectize.addOption( options );
            selectize.refreshOptions(false);
        },
      
        create: function ( conf ) {
            var container = $('<div/>');
            conf._input = $('<select/>')
                    .attr( $.extend( {
                        id: conf.id
                    }, conf.attr || {} ) )
                .appendTo( container );
      
            conf._input.selectize( $.extend( {
                valueField: 'value',
                labelField: 'label',
                searchField: 'label',
                dropdownParent: 'body'
            }, conf.opts ) );
     
            conf._selectize = conf._input[0].selectize;
     
            if ( conf.options || conf.ipOpts ) {
                _fieldTypes.selectize._addOptions( conf, conf.options || conf.ipOpts );
            }
     
            // Make sure the select list is closed when the form is submitted
            this.on( 'preSubmit', function () {
                conf._selectize.close();
            } );
      
            return container[0];
        },
      
        get: function ( conf ) {
            return conf._selectize.getValue();
        },
      
        set: function ( conf, val, localUpdate ) {
            if (! localUpdate) {
                conf._lastSet = val;
            }
    
            return conf._selectize.setValue( val );
        },
      
        enable: function ( conf ) {
            conf._selectize.enable();
            $(conf._input).removeClass( 'disabled' );
        },
      
        disable: function ( conf ) {
            conf._selectize.disable();
            $(conf._input).addClass( 'disabled' );
        },
      
        // Non-standard Editor methods - custom to this plug-in
        inst: function ( conf ) {
            return conf._selectize;
        },
     
        update: function ( conf, options ) {
            _fieldTypes.selectize._addOptions( conf, options );
    
            let lastSet = conf._lastSet;
    
            if (lastSet !== undefined) {
                _fieldTypes.selectize.set(conf, lastSet, true);
            }
        },
     
        canReturnSubmit: function () {
            return true;
        }
    };
     
     
    }));
    

    I haven't tested it, so possibly I've missed something noddy! But hopefully that will be fairly close.

    Allan

  • rf1234rf1234 Posts: 3,021Questions: 88Answers: 421

    Thanks will try that asap, Allan.

Sign In or Register to comment.