I’m not clear on what you mean by:
Triggering either the “change” or “change.select2” event is the only way to programmatically select an item in the Select2.
Are you saying that when you do this, you don’t want it to fire your “onchange” event handler? If so, your event handler shouldn’t fire if it’s listening for the “change” event (which is a different event from the “change.select2” event). I have confirmed this on the example in the Select2 documentation. The example doesn’t have a way to trigger the “change.select2” event, so I used the JavaScript console to trigger the “change.select2” event (it worked), and the “change” handler did not fire. For example, jQuery('select.js-states').eq(0).val('CA').trigger('change.select2');
selects “California” in the first Select2 widget, and the “Event Log” does not show the “change” event being fired. On the other hand, if you use the mouse to select an item from the Select2, the “Event Log” does show the “change” event being fired.
If your code is behaving differently, could you post it on Codepen or JSFiddle so I can look at it in more detail?