multiple select2内置ajax方法的正确使用

陆展
2023-12-01

场景

网站中很多在select比较多的时候,经常是需要使用select2的,
而在option比较多的时候, 则是必须使用的了。

分析

1.  select2内置了ajax方法,这个方法会调用jQ的$.ajax对象,而$ajax参数则是由ajax选项提供
2.  在用户被点击select2发送request 请求
3.  每次键入搜索关键词的时候也会发送请求
4.  默认传递参数 term~~搜索的关键词

select的option只会在该option被选中之后创建,这样可以提高性能。
即使是之后的select之后发生了变化,被创建的option也会一直存在

引入

    <link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
    <script src="https://cdn.bootcss.com/select2/4.0.6-rc.1/js/i18n/zh-CN.js"></script>

参考文献

简单用法 https://select2.org/data-sources/ajax
配置下项 https://select2.org/configuration/options-api

用法

下面的例子总结
1.   url   string  请求地址
2.  data  object  发送的参数,(列子是匿名函数加工过的对象)
3. processResults   function  对返回值进行处理
4. page  select2 支持分页,  (为laravel打call) 但是select2 需要服务端返回`pagination.more` 属性(true or false)
   告知select2 是不是有更多值去请求, 理想的数据是下面那样的;
   当然如果是也可以利用 processResults 自己组装(page and size and total_size 直到这些值就足够了)
5.  delay  用户键入搜索词等待$delay毫秒发送请求, 这样可以确保用户已经完成关键词的输入
6.  凡是$.ajax 使用的option 都是可以被ajax使用的
7. minimumInputLength  integer 在填充n个字符后才开始搜索
8. placeholder 普通的占位提示符
9. tags  boolean |array 允许用户自己添加搜索项项目(当键入的搜索内容不存在的时候)
10. cache  ajax的配置项
11. templateResult callback 定制搜索框被加载的时候的伪option的样式
12. templateSelection  callback  定制在option在被用户选中的时候option怎么展示 
     很重要的一种使用
     function(topic) {
     return topic.name || topic.text; //如果有返回则 使用搜索到的数据,如果没有的话 则使用
     }
// pagination.more 期望数据如下
{
  "results": [
    {
      "id": 1,
      "text": "Option 1"
    },
    {
      "id": 2,
      "text": "Option 2"
    }
  ],
  "pagination": {
    "more": true
  }
}
// 自己整理成select2 需要的格式
    processResults: function (data, params) {
      // parse the results into the format expected by Select2
      // since we are using custom formatting functions we do not need to
      // alter the remote JSON data, except to indicate that infinite
      // scrolling can be used
      params.page = params.page || 1;

      return {
        results: data.items,
        pagination: {
          more: (params.page * 30) < data.total_count
        }
      };
    },
$('#mySelect2').select2({
ajax: {
url: 'https://api.github.com/orgs/select2/repos',
data: function (params) {
    var query = {
    search: params.term,
    type: 'public',
    page: params.page || 1
    },
        // Query parameters will be ?search=[term]&type=public&page=[page]
    return query;
    }
},
processResults: function (data) {
      // Tranforms the top-level key of the response object from 'items' to 'results'
      return {
        results: data.items
      };
 },
 delay: 250 //wait 250 milliseconds before triggering the request
});

实例

@extends('layouts.app')

@section('content')
    <div class="container">
        @include('vendor.ueditor.assets')
        <style>
            .panel-body img {
                width: 100%;
            }
        </style>
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <div class="panel panel-default">
                    @if (session('status'))
                        <div class="alert alert-success">
                            {{ session('status') }}
                        </div>
                    @endif
                    <div class="panel-heading">发布问题</div>
                    {!! Form::open(['url'=> '/Question/store', 'method' => 'post']) !!}

                    <div class="panel-body">
                        <div class="form-group {{ $errors->has('title') ? ' has-error' : '' }}">
                            {!! Form::label('title', '标题') !!}
                            {!! Form::text('title', old('title'), ['class' => 'form-control', 'placeholder' => '请填写标题']) !!}
                            @if ($errors->has('title'))
                                <span class="help-block">
                                        <strong>{{ $errors->first('title') }}</strong>
                                    </span>
                            @endif
                        </div>

                        <div class="form-group">
                            {!! Form::label('topic', '话题') !!}
                            <select class="js-example-basic-multiple form-control" id="topic" name="topic[]" multiple="multiple">
                            </select>

                        </div>

                        <div class="form-group {{ $errors->has('body') ?  'has-error' : '' }}">
                            <script id="container" name="body" style="height: 300px" type="text/plain"> {{ old('body') }} </script>
                            @if($errors->has('body'))
                                <span class="help-block">
                                    <strong>{{ $errors->first('body') }}</strong>
                                </span>
                            @endif
                        </div>

                        <div class="form-group">
                            {!! Form::submit('发布', ['class' => 'btn btn-sm btn-success pull-right']) !!}
                        </div>
                        {!! Form::close() !!}
                    </div>
                    {{-- begin --}}

                        <div class="select2-result-repository clearfix">
                            <div class="select2-result-repository_meta">
                                <div class="select2-result-repository_title">
                                </div>
                            </div>
                        </div>

                    {{-- end --}}


                </div>
            </div>
        </div>
    </div>

    <!-- 实例化编辑器 -->
    <script type="text/javascript">

        $(function () {
            // var ue = UE.getEditor('container');
            var ue = UE.getEditor('container', {
                toolbars: [
                    ['bold', 'italic', 'underline', 'strikethrough', 'blockquote', 'insertunorderedlist', 'insertorderedlist', 'justifyleft', 'justifycenter', 'justifyright', 'link', 'insertimage', 'fullscreen']
                ],
                elementPathEnabled: false,
                enableContextMenu: false,
                autoClearEmptyNode: true,
                wordCount: false,
                imagePopup: false,
                autotypeset: {indent: true, imageBlockLine: 'center'}
            });
            ue.ready(function () {
                ue.execCommand('serverparam', '_token', '{{ csrf_token() }}'); // 设置 CSRF token.
            });

            // topic select2
            var url_topic = '/api/topics';
            $('.js-example-basic-multiple').select2({
                ajax: {
                    url: url_topic,
                    dataType: 'json', // 返回数据的格式
                    cache:true,
                    data: function (params) {
                        return { search: params.term };
                    },
                    processResults: function (data, params) { // select 要求返回格式必须含有 results属性
                        return {
                            results: data
                        };
                    },
                },
                // minimumInputLength:1,
                delay: 250, // 延迟发送请求
                placeholder: '选择相关话题', // 占位符
                tags : true, // 允许客户键入搜索内容
                templateResult :formatTopic, // 定制搜索框被加载的时候的伪option的样式
                templateSelection : formatToSelection,//定制在option在被用户选中的时候option怎么展示
                escapeMarkup : function (markup) {
                    return markup;
                }

            });
        });

        // topic展示元素的定制
        function formatTopic(topic) {
            return topic.name;
        }

        function formatToSelection(topic) {
            return topic.name || topic.text; //如果有返回则 使用搜索到的数据,如果没有的话 则使用输入值
        }
    </script>
@endsection
 类似资料: