Browse Source

document programmatically adding options

alexweissman 7 years ago
parent
commit
6657444d29
1 changed files with 78 additions and 10 deletions
  1. 78 10
      pages/12.programmatic-control/01.methods/docs.md

+ 78 - 10
pages/12.programmatic-control/01.methods/docs.md

@@ -9,24 +9,92 @@ never_cache_twig: true
 
 
 Select2 supports methods that allow programmatic control of the component.  
 Select2 supports methods that allow programmatic control of the component.  
 
 
-## Selecting a value
+## Programmatically adding options
 
 
-To programmatically select a value for a Select2 control, use the jQuery `.val()` method:
+New options can be added to a Select2 control programmatically by creating a new [Javascript `Option` object](https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement/Option) and appending it to the control:
 
 
 ```
 ```
-$('select').val('US'); // Select the option with a value of 'US'
-$('select').trigger('change'); // Notify any JS components that the value changed
+var data = {
+    id: 1,
+    text: 'Barn owl'
+};
+
+var newOption = new Option(data.name, data.id, false, false);
+$('#mySelect2').append(newOption).trigger('change');
+```
+
+The third parameter of `new Option(...)` determines whether the item is "default selected"; i.e. it sets the `selected` attribute for the new option.  The fourth parameter sets the options actual selected state - if set to `true`, the new option will be selected by default.
+
+### Create if not exists
+
+You can use `.find` to select the option if it already exists, and create it otherwise:
+
+```
+// Set the value, creating a new option if necessary
+if ($('#mySelect2').find("option[value='" + data.id + "']").length) {
+    $('#mySelect2').val(data.id).trigger('change');
+} else { 
+    // Create a DOM Option and pre-select by default
+    var newOption = new Option(data.name, data.id, true, true);
+    // Append it to the select
+    $('#mySelect2').append(newOption).trigger('change');
+} 
+```
+
+## Selecting an option
+
+To programmatically select an option/value for a Select2 control, use the jQuery `.val()` method:
+
+```
+$('#mySelect2').val('US'); // Select the option with a value of 'US'
+$('#mySelect2').trigger('change'); // Notify any JS components that the value changed
 ```
 ```
 
 
 Select2 will listen for the `change` event on the `<select>` element that it is attached to. When you make any external changes that need to be reflected in Select2 (such as changing the value), you should trigger this event.
 Select2 will listen for the `change` event on the `<select>` element that it is attached to. When you make any external changes that need to be reflected in Select2 (such as changing the value), you should trigger this event.
 
 
+### Preselecting options in an remotely-sourced (AJAX) Select2 
+
+For Select2 controls that receive their data from an [AJAX source](/data-sources/ajax), using `.val()` will not work.  The options won't exist yet, because the AJAX request is not fired until the control is opened and/or the user begins searching.  This is further complicated by server-side filtering and pagination - there is no guarantee when a particular item will actually be loaded into the Select2 control!
+
+The best way to deal with this, therefore, is to simply add the preselected item as a new option.  For remotely sourced data, this will probably involve creating a new API endpoint in your server-side application that can retrieve individual items:
+
+```
+// Set up the Select2 control
+$('#mySelect2').select2({
+    ajax: {
+        url: '/api/students'
+    }
+});
+
+// Fetch the preselected item, and add to the control
+var studentSelect = $('#mySelect2');
+$.ajax({
+    type: 'GET',
+    url: '/api/students/s/' + studentId
+}).then(function (data) {
+    // create the option and append to Select2
+    var option = new Option(data.full_name, data.id, true, true);
+    studentSelect.append(option).trigger('change');
+
+    // manually trigger the `select2:select` event
+    studentSelect.trigger({
+        type: 'select2:select',
+        params: {
+            data: data
+        }
+    });
+});
+```
+
+Notice that we manually trigger the `select2:select` event and pass along the entire `data` object.  This allows other handlers to [access additional properties of the selected item](/programmatic-control/events#triggering-events).
+
 ### Limiting the scope of the `change` event
 ### Limiting the scope of the `change` event
 
 
 It's common for other components to be listening to the `change` event, or for custom event handlers to be attached that may have side effects.  To limit the scope to **only** notify Select2 of the change, use the `.select2` event namespace:
 It's common for other components to be listening to the `change` event, or for custom event handlers to be attached that may have side effects.  To limit the scope to **only** notify Select2 of the change, use the `.select2` event namespace:
 
 
 ```
 ```
-$('select').val('US'); // Change the value or make some change to the internal state
-$('select').trigger('change.select2'); // Notify only Select2 of changes
+$('#mySelect2').val('US'); // Change the value or make some change to the internal state
+$('#mySelect2').trigger('change.select2'); // Notify only Select2 of changes
 ```
 ```
 
 
 ## Retrieving the selected values
 ## Retrieving the selected values
@@ -38,7 +106,7 @@ There are two ways to programmatically access the selection data: using `.select
 Calling `select2('data')` will return a JavaScript array of objects representing the current selection. Each object will contain all of the properties/values that were in the source data objects passed through `processResults` and `templateResult` callbacks (as in <a href="#data">Loading data from an array</a> and <a href="#ajax">Connecting to a remote data source</a>).
 Calling `select2('data')` will return a JavaScript array of objects representing the current selection. Each object will contain all of the properties/values that were in the source data objects passed through `processResults` and `templateResult` callbacks (as in <a href="#data">Loading data from an array</a> and <a href="#ajax">Connecting to a remote data source</a>).
 
 
 ```
 ```
-$('select').select2('data');
+$('#mySelect2').select2('data');
 ```
 ```
 
 
 ### Using a jQuery selector
 ### Using a jQuery selector
@@ -46,13 +114,13 @@ $('select').select2('data');
 Selected items can also be accessed via the `:selected` jQuery selector:
 Selected items can also be accessed via the `:selected` jQuery selector:
 
 
 ```
 ```
-$('select').find(':selected');
+$('#mySelect2').find(':selected');
 ```
 ```
 
 
 It is possible to extend the `<option>` elements representing selection with the HTML data-* attributes containing arbitrary data from the source data objects:
 It is possible to extend the `<option>` elements representing selection with the HTML data-* attributes containing arbitrary data from the source data objects:
 
 
 ```
 ```
-$('select').select2({
+$('#mySelect2').select2({
   // ...
   // ...
   templateSelection: function (data, container) {
   templateSelection: function (data, container) {
     $(data.element).attr('data-custom-attribute', data.customValue);
     $(data.element).attr('data-custom-attribute', data.customValue);
@@ -61,7 +129,7 @@ $('select').select2({
 });
 });
 
 
 // Retrieve custom attribute value of the first selected element
 // Retrieve custom attribute value of the first selected element
-$('select').find(':selected').attr('data-custom-attribute')
+$('#mySelect2').find(':selected').attr('data-custom-attribute')
 ```
 ```
 
 
 ## Opening the dropdown
 ## Opening the dropdown