使用 templateSelection 设置额外数据

set extra data with templateSelection

提问人:skcrpk 提问时间:10/24/2023 最后编辑:skcrpk 更新时间:10/25/2023 访问量:50

问:

当我搜索时,它可以很好地处理所有文本 id 和徽标,但现在我想添加默认数据,我可以使用 Option 添加文本和 id,但不能添加徽标

那么我如何添加来自数组的额外数据,我厌倦了使用 $(options).data 在选项中添加徽标,但这也没有用

var d = [{
  "text": "I Like It",
  "id": "427818",
  "logo": "https:\/\/cdnjs.cloudflare.com/ajax\/libs/simple-icons\/3.2.0\/pandora.svg"
}, {
  "text": "71. I Like It (feat. Kontra K and AK Ausserkontrolle)",
  "id": "146387",
  "logo": "https:\/\/cdnjs.cloudflare.com\/ajax/libs\/simple-icons\/3.2.0\/deezer.svg"
}];

searchfocussongs(d);

function searchfocussongs(data) {

  var apiurl = "";
  var curartistid = "";

  $("#sm_report_focussongs").select2({
    minimumInputLength: 2,
    width: 'resolve',
    templateResult: searchfocussongs_template,
    templateSelection: searchfocussongs_template,
    ajax: {
      url: apiurl + "?f=searchSmSongs&aid=" + curartistid,
      dataType: "json",
      type: "GET",
      processResults: function(data) {
        //console.log(data);
        return {
          results: $.map(data, function(item) {
            return {
              text: item.text,
              id: item.id,
              logo: item.logo
            }
          })
        };
      }
    }
  });

  if (data.length > 0) {

    $(data).each(function() {
      var option = new Option(this.text, this.id, true, true);
      $(option).data('logo', this.logo);
      $("#sm_report_focussongs").append(option).trigger('change');
    });

    $("#sm_report_focussongs").trigger({
      type: 'select2:select',
      params: {
        data: data
      }
    });
  }
}

function searchfocussongs_template(ar) {
  var item = $(
    '<span><img src="' + ar.logo + '"  style="height:20px;width:20px;" /> ' + ar.text + '</span>'
  );
  return item;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://rawgit.com/select2/select2/master/dist/js/select2.js"></script>
<link href="https://rawgit.com/select2/select2/master/dist/css/select2.min.css" rel="stylesheet" />
<select class="form-control" multiple="multiple" id="sm_report_focussongs" style="width:100%">

javascript jquery-select2

评论

0赞 mandy8055 10/24/2023
您正在您的函数中使用,但它来自哪里?在您的函数中,您需要添加ar.logosearchfocussongs_template$(option).data('logo', this.logo);
0赞 skcrpk 10/24/2023
@mandy8055我添加了它,但它仍然没有显示徽标 $(data).each(function () { var option = new Option(this.text, this.id, true, true); $(option).data('logo', this.logo); $(“#sm_report_focussongs”).append(option).trigger('change');
0赞 skcrpk 10/24/2023
@CBroe processResults 工作正常,当数据来自 ajax 时,它也可以正确显示徽标文本,问题出在默认数据 (var d) 上,它不显示徽标,正如您在运行代码片段时看到的那样

答:

1赞 Diego D 10/24/2023 #1

我添加了一个完整的演示,也涵盖了搜索场景。为了实现这一点,我重新定义了函数,当调用该函数时,该函数会根据搜索参数返回一个模拟 ajax 响应,其中包含一组经过过滤的歌曲。$.ajaxhttp://bogusendpoint/

在我的第一个答案中,我快速而肮脏,没有解决这个问题,因此给定的解决方案没有考虑到在具有不同条件的不同场景中调用回调函数的事实。正如您在评论中指出的那样,检查“state.logo”是否未定义是合适的,在这种情况下,请改为获取数据属性。

//list of real logo names from siple-icons
const logos = [ "spotify", "pandora", "deezer", "apple", "tidal", "youtube", "amazon", "soundcloud" ];

//list of real songs titles
const songTitles = [ "Imagine", "One", "Billie Jean", "Bohemian Rhapsody", "Hey Jude", "Like a Rolling Stone", "I Can't Stop Loving You", "Sweet Child o' Mine", "Under Pressure", "Hotel California", "Thriller", "Stairway to Heaven", "Shake it Off", "Halo", "Happy", "Despacito", "Shape of You", "Roar", "Jump", "Smooth Criminal" ];

function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

//create a list of 50 {id,text,logo,artistId} made up from thin air
let songsArray = Array.from({length: 50}).map(() => ({
  id: getRandom(100000, 999999),
  text: songTitles[getRandom(0, songTitles.length - 1)],
  logo: `https://cdnjs.cloudflare.com/ajax/libs/simple-icons/3.2.0/${logos[getRandom(0, logos.length - 1)]}.svg`,
  artistId: getRandom(1, 10)
}));

//filter the songsArray returning the subset matching artistId exact number and term as a word contained in .text
function filterSongs(songsArray, term, artistId) {
    return songsArray.filter(song =>
        song.text.toLowerCase().includes(term.toLowerCase()) &&
        (artistId == '' || song.artistId === artistId)
    );
}

//redefine the $.ajax function...
(function ($) {
    var originalAjax = $.ajax;
    $.ajax = function (params) {
        //listening to the url http://bogusendpoint/
        if (params.url.indexOf('http://bogusendpoint/') === 0) {

            //support for GET params populating the keyValues properties bag
            var queryString = params.url.split('?')[1];
            var keyValues = {};
            if (queryString) {
                queryString.split('&').forEach(function (pair) {
                    var keyValue = pair.split('=');
                    keyValues[keyValue[0]] = decodeURIComponent(keyValue[1]);
                });
            }

            //query will contain both params.data and the querystring keyValues
            const query = {...keyValues, ...params.data};

            let results = [];

            //if the f param is searchSmSongs
            if('f' in query && query.f === 'searchSmSongs'){
                //grab the query terms from the request
                let searchParam_q = '';
                let searchParam_artistId = '';
                if ('q' in query) searchParam_q = query.q;
                if ('aid' in query) searchParam_artistId = query.aid;
                //filter the songs full set
                const filteredSongs =
                  filterSongs(songsArray, searchParam_q, searchParam_artistId);
                //and prepare a response object with the filtered set
                results = filteredSongs;
            }

            //resolve and return the "promise"
            var deferred = $.Deferred();
            deferred.resolve(results);
            if (params.success) params.success(results);
            return deferred.promise();
        }

        //if the endpoint differs, call and return the original ajax function
        return originalAjax.apply($, arguments);
    }

})(jQuery);

//init the select2
const apiurl = 'http://bogusendpoint/'
const artistId = '';
$("#sm_report_focussongs").select2({
    minimumInputLength: 2,
    width: 'resolve',
    templateResult: searchfocussongs_template,
    templateSelection: searchfocussongs_template,
    ajax: {
        url: `${apiurl}`,
        dataType: "json",
        type: "GET",
        data: function(params) {
            return { f: 'searchSmSongs', aid: artistId, q: params.term };
        },
        processResults: function(data) {
            return {
              results: data.map(item => (
                { text: item.text, id: item.id, logo: item.logo }
              ))
            }
        }
    }
});

const baseurl = 'https://cdnjs.cloudflare.com/ajax/libs/simple-icons/3.2.0/';
var staticSongs = [
    { text: 'I Like It', id: 427818, logo: `${baseurl}/pandora.svg` },
    {
      text: '71. I Like It (feat. Kontra K and AK Ausserkontrolle)',
      id: 146387,
      logo: `${baseurl}/deezer.svg`
    }
];
addAndSelectSongs(staticSongs);

function addAndSelectSongs(songs){
    songs.forEach((song) => {
        var option = new Option(song.text, song.id, true, true);
        $(option).data('logo', song.logo);
        $("#sm_report_focussongs").append(option).trigger('change');
        $("#sm_report_focussongs")
          .trigger({ type: 'select2:select', params: {data: song} });
    });
}

function searchfocussongs_template(state){
    if (!state.id) {
        return state.text;
    }

    let logoSrc = state.logo;
    if(!state.logo)
        logoSrc = $(state.element).data('logo');
    
    return $(`<span><img src="${logoSrc}" style="height:20px;width:20px;" />${state.text}</span>`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<script src="https://rawgit.com/select2/select2/master/dist/js/select2.js"></script>
<link href="https://rawgit.com/select2/select2/master/dist/css/select2.min.css" rel="stylesheet" />

<select
    id="sm_report_focussongs"
    class="form-control"
    multiple="multiple"
    style="width:100%"></select>

快速和肮脏的解决方案 - 使用徽标 src 的数据属性

由于您没有将参数中的属性传递给 ,因此您可以使用任何目标元素的数据属性,该属性可以在以后的任何时间在该特定上下文中检索。.logoarsearchfocussongs_template<option>ar.element

下面是一个精简的示例,将重点介绍该特定问题:

var d = [
    {
        "text": "I Like It",
        "id": "427818",
        "logo": "https:\/\/cdnjs.cloudflare.com\/ajax\/libs/simple-icons\/3.2.0\/pandora.svg"
    },
    {
        "text": "71. I Like It (feat. Kontra K and AK Ausserkontrolle)",
        "id": "146387",
        "logo": "https:\/\/cdnjs.cloudflare.com\/ajax/libs\/simple-icons\/3.2.0\/deezer.svg"
    }
];

searchfocussongs(d);

function searchfocussongs(data) {
    if (data.length > 0) {
        $(data).each(function() {
            //you are creating an option element saying defaultSelected=true and selected=true for all of them!
            var option = new Option(this.text, this.id, true, true);
            //setting the data-logo attribute for the new option element
            $(option).data('logo', this.logo);
            $("#sm_report_focussongs").append(option).trigger('change');
        });
    }

    $("#sm_report_focussongs").select2({
        minimumInputLength: 2,
        width: 'resolve',
        templateResult: searchfocussongs_template,
        templateSelection: searchfocussongs_template,
    });
}

function searchfocussongs_template(ar) {
  //and I'm fetching the logo data retrieving the information from ar.element through its data attribute value
  var item =
    $(
      '<span><img src="' + $(ar.element).data('logo') +
      '"  style="height:20px;width:20px;" /> ' + ar.text + '</span>'
    );
  return item;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://rawgit.com/select2/select2/master/dist/js/select2.js"></script>
<link href="https://rawgit.com/select2/select2/master/dist/css/select2.min.css" rel="stylesheet" />
<select class="form-control" multiple="multiple" id="sm_report_focussongs" style="width:100%">

评论

0赞 skcrpk 10/24/2023
是的,它有效,但不适用于 processresults,但我明白为什么它在这里不起作用是我所做的函数 searchfocussongs_template(ar) { var logo = “”;if (typeof ar.logo == 'undefined'){ logo = $(ar.element).data('logo');else{ logo = ar.logo; } var item = $( '<span><img src=“' + logo + '” style=“height:20px;width:20px;“ /> ' + ar.text + '</span>' );退货;}
0赞 Diego D 10/25/2023
@skcrpk我明白你在说什么,现在我花时间正确地解决了整个场景,并包括搜索功能。您已经有了确切的解决方案,但是处理ajax模拟响应对我来说很有趣,这是值得的