【问题标题】:Chain Select2 via AJAX通过 AJAX 的链 Select2
【发布时间】:2020-12-20 00:23:47
【问题描述】:

我希望实现两件事:

  1. 允许选择选项可搜索和可过滤。

  2. 如果给定选项只有 1 个,则自动选择值

下面的代码实现了我的第 1 点,但我不确定根据当前的实现如何实现我的第 2 点。选择一个值会添加到args,因此当一个 select2 打开时,它会使用更新的args 查询数据库并返回过滤选项针对特定的 select2。工作版本如下所示:

jQuery( 'document' ).ready( function( $ ) {
            
    let select2s = [];
    let args = {};
    
    
    /**
     * Clear select2 values
     */
    function clear_select2s( except_name ) {
        
        except_name = ( 'undefined' !== typeof except_name ) ? except_name : '';
        
        select2s.forEach( function( $select2, key ) {
            if( $select2.attr( 'name' ) == except_name ) { return; }
            $select2.val( '' );
        } );
        
    }
    
    
    /**
     * Initialize select2s
     */
    $( '#s2Container .select2' ).each( function() {
        
        let name = $( this ).attr( 'name' );
        let placeholder = $( this ).attr( 'placeholder' );
        let $select2 = $( this ).select2( {
            allowClear: true,
            placeholder: placeholder,
            ajax: {
                type: 'post',
                url: test.ajaxurl,
                dataType: 'json',
                data: function( params ) {
                    return {
                        action: 'select2_filtering',
                        return: name,
                        args: Object.assign( args, {
                            'search': params.term
                        } ),
                    };
                },
                processResults: function( response ) {
                    return {results: response.data.options};
                },
            },
        } );
        
        /* Push select into Array */
        select2s.push( $select2 );
    } );
    
    
    /**
     * Remove selected value from arguments
     */
    $( '#s2Container .select2' ).on( 'select2:unselecting', function() {
        
        let name = $( this ).attr( 'name' );
        args[ name ] = '';
        
        clear_select2s();
        
    } );
    
    /**
     * Add selected value to arguments
     */
    $( '#s2Container .select2' ).on( 'select2:select', function() {
        
        let name = $( this ).attr( 'name' );
        let value = $( this ).val();
        
        Object.assign( args, {[name]:value} );
        
        clear_select2s( name );
        
    } );
    
} );

HTML

<div id="s2Container">
    <select class="select2" name="product_id" placeholder="Select Product"></select>
    <select class="select2" name="category_id" placeholder="Select Category"></select>
    <select class="select2" name="brand_id" placeholder="Select Brand"></select>
</div>

上面的代码通过 ajax 过滤了选择选项,太好了。问题是我的返回只返回当前select2的选项。

如果我为所有选择返回 all 选项的数据,那么我的理解是我需要完全重建每个 select2。销毁和重建 select2 然后失去 ajax 功能。在processResults 内执行所有这些操作似乎有缺陷,我不确定更好的方法。


如果我将其分解为 2 个 ajax 调用,一个用于 select2 选项的初始加载,一个用于处理 on( 'select2:select' ),那么我最终会得到比我需要的更多的 ajax 调用,并且我的 select2:select ajax 被覆盖最初的 select2 实例 ajax。


动态填充多个 select2 选项的最佳方法是什么?如果返回的选项计数仅为 1,我将如何设置选定的值?

【问题讨论】:

  • 我很熟悉这个关于chaining select2s 的类似问题,但它非常笼统,并没有真正回答我的任何问题。它不像范围那么简单,我的选择器是通用的并且没有 ID。

标签: javascript jquery ajax jquery-select2


【解决方案1】:

Select2 使得切换活动选项变得非常困难。我必须确保 select2 是 .empty() 然后我必须销毁实例并使用相同的设置重新创建整个事物。这是一种痛苦。最后,我决定不使用 select2 ajax 填充并在初始化后填充它们更容易。这是我想出的:

jQuery( 'document' ).ready( function( $ ) {
            
    let args = {};
    
    
    /**
     * Update all select2s with fresh options
     */
    function update_select2s() {
        
        $.ajax( {
            type: 'post',
            url: test.ajaxurl,
            dataType: 'json',
            data: {
                action: 'product_filtering',
                args: args,
            },
            success: function( response ) {
                
                let options = response.data.results;
                
                for( const [ key, values ] of Object.entries( options ) ) {
                    
                    if( ! $( '#s2Container select[name="' + key + '"]' ).length ) {
                        continue;
                    }
                    
                    let $select2    = $( '#s2Container select[name="' + key + '"]' );
                    let selected    = $select2.val();
                    let name        = $select2.attr( 'name' );
                    let placeholder = $select2.attr( 'placeholder' );
                    
                    /**
                     * If we have a select2, empty and destroy it.
                     * This will allow us to reinitialize the select2 with fresh options.
                     * Select2 instance is not yet initialized on first run.
                     */
                    if( $select2.data( 'select2' ) ) {
                        $select2.empty().select2( 'destroy' );
                    }
                    
                    $select2.select2( {
                        allowClear: true,
                        placeholder: placeholder,
                        data: values,
                    } );
                    
                    /**
                     * If there is only one option, select 2 automatically.
                     */
                    if( values.length > 1 ) {
                        $select2.val( '' ).trigger( 'change.select2' );
                    }
                    
                }
                
            }
        } );
        
    }
    
    /* Populate Select2 options */
    update_select2s();
    
    
    $( '#s2Container .select2' ).on( 'select2:unselect', function() {

        let name = $( this ).attr( 'name' );
        delete args[ name ];
        
        update_select2s();
        
    } );
    
    
    $( '#s2Container .select2' ).on( 'select2:select', function() {
        
        let name = $( this ).attr( 'name' );
        let value = $( this ).val();
        
        /**
         * If a named arg already exists, this means the user wants change
         * We need to clear our args and give our select2s fresh data.
         */
        if( args.hasOwnProperty( name ) && args[name].length ) {
            args = {[name]:value};
        } else {
            Object.assign( args, {[name]:value} );
        }
        
        update_select2s();
        
    } );
    
} );

通过此更新,我也不会返回特定 select2 的数据,而是所有 select2s。返回由选择名称键入的数据:

{
    product_id: [ {id: 1, text: 'foo'}, {id: 1,text: 'foo'} ],
    category_id: [ {id: 1,text: 'xyz'}, {id: 1,text: '123'} ],
}

【讨论】:

    猜你喜欢
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2016-06-04
    • 2016-04-16
    • 2015-06-24
    • 2012-11-01
    相关资源
    最近更新 更多