2015-05-19 19 views
82

Ich habe eine select2 v4.0.0 aus einem Ajax-Array gefüllt. Wenn ich das val des select2 setze, kann ich via Javascript debuggen, dass es das korrekte Einzelteil vorgewählt hat (# 3 in meinem Fall), jedoch wird dieses nicht im auserwählten Kasten gezeigt, es zeigt noch den Platzhalter an. enter image description hereSelect2 4.0.0 Initialwert mit Ajax

Während ich soll in etwa so sehen werden: enter image description here

In meinen Formularfeldern:

<input name="creditor_id" type="hidden" value="3"> 
<div class="form-group minimal form-gap-after"> 
    <span class="col-xs-3 control-label minimal"> 
     <label for="Creditor:">Creditor:</label> 
    </span> 
    <div class="col-xs-9"> 
     <div class="input-group col-xs-8 pull-left select2-bootstrap-prepend"> 
      <select class="creditor_select2 input-xlarge form-control minimal select2 col-xs-8"> 
       <option></option> 
      </select> 
     </div> 
    </div> 
</div> 

Mein javascript:

var initial_creditor_id = "3"; 
$(".creditor_select2").select2({ 
    ajax: { 
     url: "/admin/api/transactions/creditorlist", 
     dataType: 'json', 
     delay: 250, 
     data: function (params) { 
      return { 
       q: params.term, 
       c_id: initial_creditor_id, 
       page: params.page 
      }; 
     }, 
     processResults: function (data, page) { 
      return { 
       results: data 
      }; 
     }, 
     cache: true 
    }, 
    placeholder: "Search for a Creditor", 
    width: "element", 
    theme: "bootstrap", 
    allowClear: true 
    }).on("select2:select", function (e) { 
     var selected = e.params.data; 
     if (typeof selected !== "undefined") { 
      $("[name='creditor_id']").val(selected.creditor_id); 
      $("#allocationsDiv").hide(); 
      $("[name='amount_cash']").val(""); 
      $("[name='amount_cheque']").val(""); 
      $("[name='amount_direct']").val(""); 
      $("[name='amount_creditcard']").val(""); 
     } 
    }).on("select2:unselecting", function (e) { 
     $("form").each(function() { 
      this.reset() 
     }); 
     ("#allocationsDiv").hide(); 
     $("[name='creditor_id']").val(""); 
    }).val(initial_creditor_id); 

Wie kann ich die Auswahlbox machen Zeigen Sie das ausgewählte Element anstelle des Platzhalters? Soll ich das vielleicht als Teil der AJAX JSON Antwort senden?

In der Vergangenheit benötigte Select2 eine Option namens initSelection, die immer dann definiert wurde, wenn eine benutzerdefinierte Datenquelle verwendet wurde, sodass die anfängliche Auswahl für die zu bestimmende Komponente möglich war. Das funktionierte für mich in Version 3.5.

+0

Wie seine möglich? Wenn ich verbinde 'select' mit' ajax' versuche, steigt der Fehler, diese Option ajax ist nicht erlaubt mit select ... – Daggeto

+0

Hallo, bitte schaut euch http://stackoverflow.com/questions/42833778/ember- select-2-issue-while-using-type-ahead-with-ajax-Abfragen – vivek

Antwort

95

Sie machen die meisten Dinge richtig, es sieht so aus, als ob das einzige Problem, das Sie treffen, ist, dass Sie die Methode change nicht auslösen, nachdem Sie den neuen Wert eingestellt haben. Ohne ein Ereignis change kann Select2 nicht wissen, dass der zugrunde liegende Wert geändert wurde, so dass nur der Platzhalter angezeigt wird. Ändern Sie Ihren letzten Teil zu

Sollte Ihr Problem beheben, und Sie sollten sofort die Benutzeroberfläche aktualisieren.


Das setzt voraus, dass Sie eine <option> bereits haben, dass ein value von initial_creditor_id hat. Wenn Sie nicht über Select2 und den Browser verfügen, können Sie den Wert nicht ändern, da es keine Option zum Wechseln gibt und Select2 den neuen Wert nicht erkennt. Ich habe festgestellt, dass Ihre <select> nur eine einzige Option enthält, die für den Platzhalter, was bedeutet, dass Sie die neue <option> manuell erstellen müssen.

var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display"); 

Und dann hängen Sie ihn an die <select>, die Sie Select2 auf initialisiert. Möglicherweise müssen Sie den Text von einer externen Quelle beziehen, wo initSelection verwendet wird, um ins Spiel zu kommen, was mit Select2 4.0.0 noch möglich ist. Wie bei einer Standard-Auswahl bedeutet dies, dass Sie die AJAX-Anfrage stellen müssen, um den Wert abzurufen, und dann den Text <option> im laufenden Betrieb anpassen.

var $select = $('.creditor_select2'); 

$select.select2(/* ... */); // initialize Select2 and any events 

var $option = $('<option selected>Loading...</option>').val(initial_creditor_id); 

$select.append($option).trigger('change'); // append the option and update Select2 

$.ajax({ // make the request for the selected data object 
    type: 'GET', 
    url: '/api/for/single/creditor/' + initial_creditor_id, 
    dataType: 'json' 
}).then(function (data) { 
    // Here we should have the data object 
    $option.text(data.text).val(data.id); // update the text that is displayed (and maybe even the value) 
    $option.removeData(); // remove any caching data that might be associated 
    $select.trigger('change'); // notify JavaScript components of possible changes 
}); 

Während dies wie eine Menge Code aussehen kann, ist dies genau, wie Sie es für Nicht-Select2 Auswahlbox, dass alle Änderungen vorgenommen wurden, um sicherzustellen, tun würden.

+1

Das funktioniert fast. Das zurückgegebene DataObject ist wahrscheinlich ein Array von Objekten mit einem einzelnen Objekt, also muss ich für ein einzelnes Objekt wahrscheinlich etwas zurückgeben: '$ option.text (data [0] .text) .val (data [0 ] .id); 'oder wenn ich ein Array aller möglichen Optionen zurückbekomme:' if (initial_creditor_id> 0) { var initial = jQuery.grep (Daten, Funktion (ausgewählt) { return selected.creditor_id = = initial_creditor_id }); $ option.text (initial [0] .text); $ option.val (initial [0] .creditor_id); ' – Greg

+10

Haben Sie eine Idee, wie Sie mehrere Optionen für Multi-Select-Boxen vorwählen können? – user396404

+5

@ user396404 die gleichen Konzepte sollten gelten, übergeben Sie einfach eine Liste von IDs in 'val()' anstelle einer einzelnen ID. Oder fügen Sie einfach mehrere '

-4

Hallo war fast das Beenden und gehen Sie zurück, um 3.5.1 zu wählen. Aber endlich habe ich die Antwort bekommen!

$('#test').select2({ 
    placeholder: "Select a Country", 
    minimumResultsForSearch: 2, 
    ajax: { 
     url: '...', 
     dataType: 'json', 
     cache: false, 
     data: function (params) { 
       var queryParameters = { 
        q: params.term 
       } 
       return queryParameters; 
     }, 
     processResults: function (data) { 
      return { 
       results: data.items 
      }; 
     } 
    } 
}); 

var option1 = new Option("new",true, true); 

$('#status').append(option1); 

$('#status').trigger('change'); 

Stellen Sie sicher, dass die neue Option eine der select2-Optionen ist. Ich bekomme das von einem JSon.

+0

Hallo - was ist "#status"? sollte das "#test" sein? – user2808054

3

Das Problem der gezwungen zu trigger('change') fuhr mich verrückt, als ich benutzerdefinierte Code in der Trigger hatte, die nur auslösen sollte, wenn der Benutzer die Option im Dropdown ändert. IMO, Änderung sollte nicht ausgelöst werden, wenn am Anfang ein Init-Wert gesetzt wird.

Ich grub tief und fanden die folgende: https://github.com/select2/select2/issues/3620

Beispiel:

$dropDown.val(1).trigger('change.select2');

21

Was ich getan habe, ist mehr sauber und braucht zwei Arrays zu machen:

  • man enthält eine Liste von Object mit ID und einem Text (in meinem Fall die ID und der Name, abhängig von Ihrem Templ ateResult) (dessen, was Sie von Ajax-Abfrage erhalten)
  • die zweite ist nur ein Array von IDs (Selektionswert)

ich initialisieren select2 das erste Array als Daten verwendet wird, und die zweite als val.

Eine Beispielfunktion mit als Parameter ein dict von id: name.

function initMyList(values) { 
    var selected = []; 
    var initials = []; 

    for (var s in values) { 
     initials.push({id: s, name: values[s].name}); 
     selected.push(s); 
    } 

    $('#myselect2').select2({ 
     data: initials, 
     ajax: { 
      url: "/path/to/value/", 
      dataType: 'json', 
      delay: 250, 
      data: function (params) { 
       return { 
        term: params.term, 
        page: params.page || 1, 
       }; 
      }, 
      processResults: function (data, params) { 
       params.page = params.page || 1; 

       return { 
        results: data.items, 
        pagination: { 
         more: (params.page * 30) < data.total_count 
        } 
       }; 
      }, 
      cache: true 
     }, 
     minimumInputLength: 1, 
     tokenSeparators: [",", " "], 
     placeholder: "Select none, one or many values", 
     templateResult: function (item) { return item.name; }, 
     templateSelection: function (item) { return item.name; }, 
     matcher: function(term, text) { return text.name.toUpperCase().indexOf(term.toUpperCase()) != -1; }, 
    }); 

    $('#myselect2').val(selected).trigger('change'); 
} 

können Sie speisen den Initialen Wert Ajax-Aufrufe verwenden, und die Verwendung von Jquery verspricht die select2 Initialisierung zu tun.

+2

Dies ist definitiv der bessere Weg, es zu tun. Das DOM zu manipulieren, indem '

+2

@ Firebird631 tun, ist Ihre Lösung brillant, es funktioniert und sehr großen Dank! – userlond

+0

Dies ist die sauberste Lösung, die ich bis jetzt gesehen habe –

0

Ich füge diese Antwort hauptsächlich hinzu, weil ich oben nicht kommentieren kann! Ich fand, dass es der Kommentar von @Nicki und ihrem Freund, https://jsfiddle.net/57co6c95/ war, der das schließlich für mich funktionierte.

Unter anderem gab es Beispiele für das Format für die Json erforderlich. Die einzige Änderung, musste ich machen war, dass meine ersten Ergebnisse im gleichen Format wie der anderen Ajax-Aufruf zurückgegeben wurden, so hatte ich

$option.text(data[0].text).val(data[0].id); 

statt

$option.text(data.text).val(data.id); 
2

Ein Szenario zu verwenden, die ich haven‘ t gesehene Leute wirklich antworten, ist, wie man eine Vorauswahl hat, wenn die Wahlen AJAX Ursprungs sind, und Sie können mehrere wählen. Da dies die Einstiegsseite für die AJAX-Vorauswahl ist, füge ich hier meine Lösung hinzu.

$('#mySelect').select2({ 
    ajax: { 
     url: endpoint, 
     dataType: 'json', 
     data: [ 
      { // Each of these gets processed by fnRenderResults. 
       id: usersId, 
       text: usersFullName, 
       full_name: usersFullName, 
       email: usersEmail, 
       image_url: usersImageUrl, 
       selected: true // Causes the selection to actually get selected. 
      } 
     ], 
     processResults: function(data) { 

      return { 
       results: data.users, 
       pagination: { 
        more: data.next !== null 
       } 
      }; 

     } 
    }, 
    templateResult: fnRenderResults, 
    templateSelection: fnRenderSelection, // Renders the result with my own style 
    selectOnClose: true 
}); 
1

nach ein paar Stunden auf der Suche nach einer Lösung, beschloss ich, meine eigenen zu erstellen. Er ist es:

function CustomInitSelect2(element, options) { 
      if (options.url) { 
       $.ajax({ 
        type: 'GET', 
        url: options.url, 
        dataType: 'json' 
       }).then(function (data) { 
        element.select2({ 
         data: data 
        }); 
        if (options.initialValue) { 
         element.val(options.initialValue).trigger('change'); 
        } 
       }); 
      } 
     } 

Und Sie können die wählt mit dieser Funktion initialisieren:

$('.select2').each(function (index, element) { 
      var item = $(element); 
      if (item.data('url')) { 
       CustomInitSelect2(item, { 
        url: item.data('url'), 
        initialValue: item.data('value') 
       }); 
      } 
      else { 
       item.select2(); 
      } 
     }); 

Und natürlich ist hier die html:

<select class="form-control select2" id="test1" data-url="mysite/load" data-value="123"></select> 
+0

Großartige Idee für ein generisches Initialisierungsverfahren. –

0

Erstellen Sie einfache Ajax-Combo mit de initial selected value für select2 4.0.3

<select name="mycombo" id="mycombo""></select>     
<script> 
document.addEventListener("DOMContentLoaded", function (event) { 
    selectMaker.create('table', 'idname', '1', $("#mycombo"), 2, 'type');         
}); 
</script> 

Bibliothek.js

var selectMaker = { 
create: function (table, fieldname, initialSelected, input, minimumInputLength = 3, type ='',placeholder = 'Select a element') { 
    if (input.data('select2')) { 
     input.select2("destroy"); 
    } 
    input.select2({ 
     placeholder: placeholder, 
     width: '100%', 
     minimumInputLength: minimumInputLength, 
     containerCssClass: type, 
     dropdownCssClass: type, 
     ajax: { 
      url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type, 
      type: 'post', 
      dataType: 'json', 
      contentType: "application/json", 
      delay: 250, 
      data: function (params) { 
       return { 
        term: params.term, // search term 
        page: params.page 
       }; 
      }, 
      processResults: function (data) { 
       return { 
        results: $.map(data.items, function (item) { 
         return { 
          text: item.name, 
          id: item.id 
         } 
        }) 
       }; 
      } 
     } 
    }); 
    if (initialSelected>0) { 
     var $option = $('<option selected>Cargando...</option>').val(0); 
     input.append($option).trigger('change'); // append the option and update Select2 
     $.ajax({// make the request for the selected data object 
      type: 'GET', 
      url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type + '&initialSelected=' + initialSelected, 
      dataType: 'json' 
     }).then(function (data) { 
      // Here we should have the data object 
      $option.text(data.items[0].name).val(data.items[0].id); // update the text that is displayed (and maybe even the value) 
      $option.removeData(); // remove any caching data that might be associated 
      input.trigger('change'); // notify JavaScript components of possible changes 
     }); 
    } 
} 
}; 

und der PHP-Server-Seite

<?php 
if (isset($_GET['getQuery']) && isset($_GET['table']) && isset($_GET['fieldname'])) { 
//parametros carga de petición 
parse_str(file_get_contents("php://input"), $data); 
$data = (object) $data; 
if (isset($data->term)) { 
    $term = pSQL($data->term); 
}else{ 
    $term = ''; 
} 
if (isset($_GET['initialSelected'])){ 
    $id =pSQL($_GET['initialSelected']); 
}else{ 
    $id = ''; 
} 
if ($_GET['table'] == 'mytable' && $_GET['fieldname'] == 'mycolname' && $_GET['type'] == 'mytype') { 

    if (empty($id)){ 
     $where = "and name like '%" . $term . "%'"; 
    }else{ 
     $where = "and id= ".$id; 
    } 

    $rows = yourarrayfunctionfromsql("SELECT id, name 
        FROM yourtable 
        WHERE 1 " . $where . " 
        ORDER BY name "); 
} 

$items = array("items" => $rows); 
$var = json_encode($items); 
echo $var; 
?> 
3

Wenn Sie eine templateSelection und Ajax verwenden, arbeiten einige dieser anderen Antworten nicht. Es scheint, dass das Erstellen eines neuen option Elements und das Setzen der value und text die Template-Methode nicht erfüllt, wenn Ihre Datenobjekte andere Werte als ID und Text verwenden. Hier

ist das, was für mich gearbeitet:

$("#selectElem").select2({ 
    ajax: { ... }, 
    data: [YOUR_DEFAULT_OBJECT], 
    templateSelection: yourCustomTemplate 
} 

Schauen Sie sich die jsFiddle hier: https://jsfiddle.net/shanabus/f8h1xnv4

In meinem Fall musste ich processResults in da meine Daten nicht enthalten die erforderlichen id und text Felder . Wenn Sie dies tun müssen, müssen Sie auch Ihre erste Auswahl über die gleiche Funktion ausführen. Wie so:

$(".js-select2").select2({ 
    ajax: { 
    url: SOME_URL, 
    processResults: processData 
    }, 
    data: processData([YOUR_INIT_OBJECT]).results, 
    minimumInputLength: 1, 
    templateSelection: myCustomTemplate 
}); 

function processData(data) { 
    var mapdata = $.map(data, function (obj) {  
    obj.id = obj.Id; 
    obj.text = '[' + obj.Code + '] ' + obj.Description; 
    return obj; 
    }); 
    return { results: mapdata }; 
} 

function myCustomTemplate(item) { 
    return '<strong>' + item.Code + '</strong> - ' + item.Description; 
} 
+0

SCHLIESSLICH !!!!! Wow, das hätte nicht frustrierender sein können !! Ich hatte "Name" anstelle von "Text" verwendet und es brachte mich um. Ich wechselte auf die Standard-Taste "Text" und es funktioniert jetzt perfekt. Vielen Dank! –

0

Für eine einfache und semantische Lösung bevorzugen i den Anfangswert in HTML zu definieren, zB:

<select name="myfield" data-placeholder="Select an option"> 
    <option value="initial-value" selected>Initial text</option> 
</select> 

Also, wenn ich $('select').select2({ ajax: {...}}); der Anfangswert nennen, ist initial-value und seine Option Text ist Initial text.

Meine aktuelle Select2-Version ist 4.0.3, aber ich denke, es hat eine große Kompatibilität mit anderen Versionen.

1

Es Arbeiten für mich ...

Verwenden Sie jQuery nicht nur HTML: Erstellen Sie die -Value-Option Sie wird angezeigt, wie ausgewählt. Wenn ID ist in select2 Daten wird automatisch ausgewählt.

<select id="select2" name="mySelect2"> 
    <option value="mySelectedValue"> 
     Hello, I'm here! 
    </option> 
</select> 

Select2.org - Default Pre Selected values

+0

einfache Lösung und es funktioniert :) Vielen Dank @Jea –